summaryrefslogtreecommitdiff
path: root/cleopatre/buildroot/toolchain/kernel-headers
diff options
context:
space:
mode:
authorlefranc2008-08-01 09:25:43 +0000
committerlefranc2008-08-01 09:25:43 +0000
commit9a2bcc0b92b392f1f21cd26927515e4d49bc128e (patch)
treed0bd193c764606c4c6e4b4568ef08d0ff3324b72 /cleopatre/buildroot/toolchain/kernel-headers
parentd0cc0304ed6eaf72116743e13e5b3b3cbfd878bb (diff)
- import of buildroot original sources (20080729 version)
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@2704 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cleopatre/buildroot/toolchain/kernel-headers')
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/Config.in138
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.20.4-ipmisensors-20070314-1214.patch1914
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.21.5-007-ipmisensors-20070314-1214.patch1914
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.1-007-ipmisensors-20070314-1214.patch1914
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.9-007-ipmisensors-20070314-1214.patch1914
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-new.makefile91
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old-versions.makefile103
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old.makefile87
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/kernel-headers.mk48
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.20.4-dwmw2-combined.01.diff460
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-001-add-linkage-header.patch18
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-006-wait-for-async-scanned-block-devices.patch55
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.23-nios2nommu.patch26567
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.25.9-export-linux-aout.patch24
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11-nios2nommu.patch.conditional13527
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0-mips-nptl.patch75
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0.patch18
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-arm-eabi.patch166
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-config-base-small.patch30
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-i2c_msg.patch12
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-mips-nptl.patch90
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.8-cleanup.patch8153
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.9-nios2nommu.patch.conditional12925
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-001-lzma-vmlinuz.00.patch27017
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-002-lzma-vmlinuz.01.patch54
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-001-lzma-vmlinuz.00.patch26856
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-002-lzma-vmlinuz.01.patch54
-rw-r--r--cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-003-lzma-vmlinuz.patch44
28 files changed, 124268 insertions, 0 deletions
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/Config.in b/cleopatre/buildroot/toolchain/kernel-headers/Config.in
new file mode 100644
index 0000000000..c512ae22bb
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/Config.in
@@ -0,0 +1,138 @@
+# Choose the kernel headers to use for kernel-headers target. This is
+# ignored if you are building your own kernel or using the system kernel.
+#
+
+comment "Kernel Header Options"
+
+choice
+ prompt "Kernel Headers"
+ default BR2_KERNEL_HEADERS_2_6_25
+
+ help
+ Select the version of kernel header files you wish to use.
+ You must select the correct set of header files to match
+ the kernel you intend to use on your target system.
+
+ For the snapshot, you have to provide the
+ linux-2.6.tar.bz2 tarball in your download dir.
+
+ config BR2_KERNEL_HEADERS_2_4_25
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.4.25 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_4_27
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.4.27 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_4_29
+ depends on !BR2_avr32 && !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.4.29 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_4_31
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.4.31 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_9
+ depends on !BR2_avr32 && BR2_DEPRECATED
+ bool "Linux 2.6.9 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_11
+ depends on !BR2_avr32 && BR2_DEPRECATED
+ bool "Linux 2.6.11 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_12
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.12 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_20_4
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.20.4 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_20
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.20.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_21_5
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.21.5 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_21
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.21.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_22_1
+ depends on !BR2_avr32 && !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.22.1 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_22_10
+ depends on !BR2_nios2 && BR2_DEPRECATED
+ bool "Linux 2.6.22.10 kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_22
+ depends on BR2_DEPRECATED
+ bool "Linux 2.6.22.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_23
+ depends on BR2_DEPRECATED
+ bool "Linux 2.6.23.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_24
+ depends on BR2_RECENT
+ bool "Linux 2.6.24.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_2_6_25
+ bool "Linux 2.6.25.x kernel headers"
+
+ config BR2_KERNEL_HEADERS_SNAP
+ bool "Linux 2.6 snapshot"
+
+endchoice
+
+config BR2_KERNEL_HEADERS_IPMI
+ bool "use ipmi kernel patches"
+ depends on BR2_KERNEL_HEADERS_2_6_20_4 || BR2_KERNEL_HEADERS_2_6_21_5 || BR2_KERNEL_HEADERS_2_6_22_1
+ help
+ Apply patches which add IPMI sensor support.
+
+config BR2_KERNEL_HEADERS_LZMA
+ bool "use lzma initramfs kernel patches"
+ depends on BR2_KERNEL_HEADERS_2_6_21_5 || BR2_KERNEL_HEADERS_2_6_22_1
+ help
+ Apply patches which allow for lzma compressed
+ initramfs filesystems. This requires the lzma
+ program in your development environment.
+
+config BR2_KERNEL_HEADERS_RT
+ bool "use realtime (-rt) kernel patches"
+ depends on BR2_KERNEL_HEADERS_2_6_21_5 || BR2_KERNEL_HEADERS_2_6_22_1
+ help
+ Apply Ingo's realtime extensions to linux
+
+config BR2_KERNEL_HEADERS_PATCH_DIR
+ bool "Add additional headers from $(KERNEL_HEADERS_PATCH_DIR)"
+ depends on BR2_KERNEL_HEADERS_2_6_20_4 || BR2_KERNEL_HEADERS_2_6_21_5 || BR2_KERNEL_HEADERS_2_6_22_1 || BR2_KERNEL_HEADERS_2_6_22_10
+ help
+ Apply additional kernel patches defined by KERNEL_HEADERS_PATCH_DIR
+ in your board directory.
+
+config BR2_DEFAULT_KERNEL_HEADERS
+ string
+ default "2.4.25" if BR2_KERNEL_HEADERS_2_4_25
+ default "2.4.27" if BR2_KERNEL_HEADERS_2_4_27
+ default "2.4.29" if BR2_KERNEL_HEADERS_2_4_29
+ default "2.4.31" if BR2_KERNEL_HEADERS_2_4_31
+ default "2.6.9" if BR2_KERNEL_HEADERS_2_6_9
+ default "2.6.11" if BR2_KERNEL_HEADERS_2_6_11
+ default "2.6.12" if BR2_KERNEL_HEADERS_2_6_12
+ default "2.6.20.4" if BR2_KERNEL_HEADERS_2_6_20_4
+ default "2.6.20.20" if BR2_KERNEL_HEADERS_2_6_20
+ default "2.6.21.5" if BR2_KERNEL_HEADERS_2_6_21_5
+ default "2.6.21.7" if BR2_KERNEL_HEADERS_2_6_21
+ default "2.6.22.1" if BR2_KERNEL_HEADERS_2_6_22_1
+ default "2.6.22.10" if BR2_KERNEL_HEADERS_2_6_22_10
+ default "2.6.22.10" if BR2_KERNEL_HEADERS_2_6_22
+ default "2.6.23" if BR2_KERNEL_HEADERS_2_6_23
+ default "2.6.24.7" if BR2_KERNEL_HEADERS_2_6_24
+ default "2.6.25.10" if BR2_KERNEL_HEADERS_2_6_25
+ default "2.6" if BR2_KERNEL_HEADERS_SNAP
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.20.4-ipmisensors-20070314-1214.patch b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.20.4-ipmisensors-20070314-1214.patch
new file mode 100644
index 0000000000..aca57c37b0
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.20.4-ipmisensors-20070314-1214.patch
@@ -0,0 +1,1914 @@
+diff -rduNp linux-2.6.20.3.orig/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.20.3/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.20.3.orig/drivers/char/ipmi/ipmi_msghandler.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/char/ipmi/ipmi_msghandler.c 2007-03-14 14:23:02.000000000 +0100
+@@ -1954,6 +1954,24 @@ static void remove_proc_entries(ipmi_smi
+ #endif /* CONFIG_PROC_FS */
+ }
+
++/*
++ * Retrieves the bmc_device struct for a given ipmi interface number (or NULL if none).
++ */
++struct device *ipmi_get_bmcdevice(int if_num)
++{
++ ipmi_smi_t intf;
++ mutex_lock(&ipmi_interfaces_mutex);
++ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
++ if (intf->intf_num == if_num){
++ mutex_unlock(&ipmi_interfaces_mutex);
++ return &intf->bmc->dev->dev;
++ }
++ }
++ mutex_unlock(&ipmi_interfaces_mutex);
++
++ return NULL;
++}
++
+ static int __find_bmc_guid(struct device *dev, void *data)
+ {
+ unsigned char *id = data;
+@@ -4183,3 +4201,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN);
+ EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+ EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+ EXPORT_SYMBOL(ipmi_free_recv_msg);
++EXPORT_SYMBOL(ipmi_get_bmcdevice);
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/Kconfig linux-2.6.20.3/drivers/hwmon/Kconfig
+--- linux-2.6.20.3.orig/drivers/hwmon/Kconfig 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/Kconfig 2007-03-14 14:23:02.000000000 +0100
+@@ -218,6 +218,16 @@ config SENSORS_GL520SM
+ This driver can also be built as a module. If so, the module
+ will be called gl520sm.
+
++config SENSORS_IPMI
++ tristate "IPMI Hardware Monitoring Support"
++ depends on HWMON && IPMI_HANDLER && EXPERIMENTAL
++ help
++ If you say yes here you get support for sensors monitored by
++ an IPMI baseboard management controller (BMC).
++
++ This driver can also be built as a module. If so, the module
++ will be called ipmisensors.
++
+ config SENSORS_IT87
+ tristate "ITE IT87xx and compatibles"
+ depends on HWMON && I2C
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/Makefile linux-2.6.20.3/drivers/hwmon/Makefile
+--- linux-2.6.20.3.orig/drivers/hwmon/Makefile 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/Makefile 2007-03-14 14:23:02.000000000 +0100
+@@ -28,6 +28,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
+ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
++obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o
+ obj-$(CONFIG_SENSORS_IT87) += it87.o
+ obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
+ obj-$(CONFIG_SENSORS_LM63) += lm63.o
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.c linux-2.6.20.3/drivers/hwmon/ipmisensors.c
+--- linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/ipmisensors.c 2007-03-14 14:44:42.000000000 +0100
+@@ -0,0 +1,1552 @@
++/*
++ * ipmisensors.c - lm-sensors/hwmon interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/init.h>
++#include <linux/module.h>
++#include <linux/param.h>
++#include <linux/hwmon.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/device.h>
++#include <linux/hwmon.h>
++
++#include "ipmisensors.h"
++
++/****** Function Prototypes ******/
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg);
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc);
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset);
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index);
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr);
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data);
++static int ipmisensors_intf_registered(int ipmi_intf);
++static int ipmisensors_bmc_registered(struct device *bmc);
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address);
++static void ipmisensors_unregister_bmc(int ipmi_intf);
++static void ipmisensors_unregister_bmc_all(void);
++static void ipmisensors_new_smi(int if_num, struct device *dev);
++static void ipmisensors_smi_gone(int if_num);
++static void ipmisensors_update_bmc(struct work_struct *);
++static void ipmisensors_cleanup(void);
++
++/****** Static Vars ******/
++
++/* set when module is being removed */
++static int cleanup = 0;
++
++/* ipmisensors driver data */
++static struct ipmisensors_data driver_data = {
++ .driver_name = "bmc",
++ .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data),
++ .interfaces = 0,
++ .smi_watcher = {
++ .owner = THIS_MODULE,
++ .new_smi = ipmisensors_new_smi,
++ .smi_gone = ipmisensors_smi_gone,
++ },
++ .ipmi_hndlrs = {
++ .ipmi_recv_hndl = ipmisensors_msg_handler,
++ },
++};
++
++/* sensor refresh workqueue */
++static struct workqueue_struct *ipmisensors_workqueue;
++
++/****** SDR List Functions ******/
++/**
++ * Creates a new sdrdata struct, or returns NULL if insufficient memory.
++ */
++static struct sdrdata *ipmisensors_new_sdr(void)
++{
++ struct sdrdata *sdr;
++
++ sdr = kmem_cache_alloc(driver_data.sdrdata_cache, GFP_ATOMIC);
++ if (sdr) {
++ memset(sdr, 0, sizeof(struct sdrdata));
++ } else {
++ printk(KERN_ERR
++ "ipmisensors: Couldn't allocate memory for new SDR\n");
++ }
++
++ return sdr;
++}
++
++/**
++ * Adds the given sdrdata struct to the given bmc's SDR list.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static inline void ipmisensors_add_sdr(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ list_add(&sdr->list, &bmc->sdrs);
++ printk(KERN_DEBUG
++ "ipmisensors: SDR %d: type 0x%02x (%s)\n",
++ bmc->sdr_count, sdr->stype, sdr->id);
++ bmc->sdr_count++;
++}
++
++/**
++ * Cleanup the sdr list for the given BMC.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_sdr_cleanup(struct ipmisensors_bmc_data *bmc)
++{
++ struct sdrdata *cursor, *next;
++
++ /* find and free each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ device_remove_file(bmc->dev, &cursor->attr.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_min.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_max.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_label.dev_attr);
++
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++
++ list_del(&cursor->list);
++ kmem_cache_free(driver_data.sdrdata_cache, cursor);
++ }
++}
++
++/* worker function for workqueue ipmisensors_workqueue */
++static void ipmisensors_update_bmc(struct work_struct *work)
++{
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, update_work.work);
++
++ /* don't start an update cycle if one already in progress */
++ if (bmc->state != STATE_READING) {
++ struct sdrdata *cursor, *next;
++ bmc->state = STATE_READING;
++ printk(KERN_DEBUG "ipmisensors: starting update\n");
++
++ /* init semaphore to 1 for update cycle */
++ sema_init(&bmc->update_semaphore, 1);
++
++ /* update each sdr reading */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ ipmisensors_get_reading(bmc, cursor);
++ }
++ }
++
++ /* wait for readings (need timeout?) */
++ down_interruptible(&bmc->update_semaphore);
++
++ printk(KERN_DEBUG "ipmisensors: update complete\n");
++
++ bmc->state = STATE_DONE;
++
++ /* if the module isn't cleaning up, schedule another update */
++ if (!cleanup)
++ queue_delayed_work(ipmisensors_workqueue, &bmc->update_work,
++ bmc->update_period * HZ);
++}
++
++/****** IPMI Message Sending ******/
++
++/**
++ * Send a message to the IPMI BMC
++ *
++ * @bmc: the bmc to send the message to.
++ * @msgid: the message id to use.
++ * @msg: the ipmi message structure.
++ */
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg)
++{
++ if (msg->data == NULL)
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x\n", msg->cmd);
++ else
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x 0x%x 0x%x\n",
++ msg->cmd, msg->data[0], msg->data[1]);
++
++ /* This should be ipmi_request, but Corey had to remove
++ * that due to it being unused at the moment, as soon as
++ * this makes it into the kernel we should request it be re-instated.
++ */
++ ipmi_request_settime(bmc->user, &bmc->address, msgid, msg, bmc, 0,
++ -1, 0);
++}
++
++/**
++ * Compose and send a "reserve SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_RESERVE_SDR;
++ bmc->tx_message.data_len = 0;
++ bmc->tx_message.data = NULL;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Componse and send a "get SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @res_id:
++ * @record:
++ * @offset:
++ */
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset)
++{
++ printk(KERN_DEBUG "ipmisensors: Get SDR 0x%x 0x%x 0x%x\n",
++ res_id, record, offset);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SDR;
++ bmc->tx_message.data_len = 6;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = res_id & 0xff;
++ bmc->tx_msg_data[1] = res_id >> 8;
++ bmc->tx_msg_data[2] = record & 0xff;
++ bmc->tx_msg_data[3] = record >> 8;
++ bmc->tx_msg_data[4] = offset;
++ bmc->tx_msg_data[5] = bmc->ipmi_sdr_partial_size;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "set sensor threshold" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @id: the ipmi id number of the sensor.
++ * @value: the new value for the threshold.
++ * @lim_index: the index in the lim[] array for which this value applies.
++ */
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index)
++{
++ int i;
++
++ printk(KERN_DEBUG "ipmisensors: Set SDR Threshold %d %d %d\n",
++ number, value, lim_index);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_SET_SENSOR_THRESHOLD;
++ bmc->tx_message.data_len = 8;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = number & 0xff;
++ bmc->tx_msg_data[1] = 0x01 << lim_index;
++
++ if (lim_index > 5 || lim_index < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Error - ipmisensors_set_sensor_threshold given invalid lim_index\n");
++ return;
++ }
++
++ for (i = 2; i < 8; i++)
++ bmc->tx_msg_data[i] = 0x00;
++
++ bmc->tx_msg_data[lim_index] = value && 0xff;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "get sensor reading" message for the given sdr.
++ *
++ * @bmc: the bmc to send the message to.
++ * @sdr: the sdr of the sensor to get the reading for.
++ */
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SENSOR_STATE_READING;
++ bmc->tx_message.data_len = 1;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = sdr->number;
++ bmc->current_sdr = sdr;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++ down_interruptible(&bmc->update_semaphore);
++}
++
++/****** IPMI Message Receiving ******/
++
++/**
++ * Process an sensor reading response message.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_reading_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ struct sdrdata *sdr = bmc->current_sdr;
++
++ if (sdr == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error ipmisensors_rcv_reading with NULL sdr\n");
++ return;
++ }
++
++ sdr->reading = msg->data[1];
++ sdr->status = msg->data[2];
++ sdr->thresholds = msg->data[3];
++
++ printk(KERN_DEBUG "ipmisensors: sensor %d (type %d) reading %d\n",
++ sdr->number, sdr->stype, msg->data[1]);
++
++ up(&bmc->update_semaphore);
++}
++
++/**
++ * Unpack based on string type, convert to normal, null terminate.
++ */
++static void ipmisensors_sprintf(u8 * to, u8 * from, u8 type, u8 length)
++{
++ static const u8 *bcdplus = "0123456789 -.:,_";
++ int i;
++
++ switch (type) {
++ case 0: /* unicode */
++ for (i = 0; i < length; i++)
++ *to++ = (*from++ & 0x7f);
++ *to = 0;
++ break;
++ case 1: /* BCD Plus */
++ for (i = 0; i < length; i++)
++ *to++ = bcdplus[*from++ & 0x0f];
++ *to = 0;
++ break;
++ case 2: /* packed ascii *//* if not a mult. of 3 this will run over */
++ for (i = 0; i < length; i += 3) {
++ *to++ = *from & 0x3f;
++ *to++ = *from >> 6 | ((*(from+1) & 0xf) << 2);
++ from++;
++ *to++ = *from >> 4 | ((*(from+1) & 0x3) << 4);
++ from++;
++ *to++ = (*from++ >> 2) & 0x3f;
++ }
++ *to = 0;
++ break;
++ case 3: /* normal */
++ if (length > 1)
++ memcpy(to, from, length);
++ to[length] = 0;
++ break;
++ }
++}
++
++/* IPMI V1.5 Section 30 */
++static const int exps[] =
++ { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
++
++/* Return 0 for fan, 2 for temp, 3 for voltage
++ We could make it variable based on the accuracy (= log10(m * 10**k2));
++ this would work for /proc output, however libsensors resolution
++ is statically set in lib/chips.c */
++static int decplaces(struct sdrdata *sd)
++{
++ switch (sd->stype) {
++ case STYPE_TEMP:
++ return 2;
++ case STYPE_CURR:
++ case STYPE_VOLT:
++ return 3;
++ case STYPE_FAN:
++ default:
++ return 0;
++ }
++}
++
++/* convert a raw value to a reading. IMPI V1.5 Section 30 */
++static long conv_val(int value, struct sdrdata *sd)
++{
++ u8 k1, k2;
++ long r;
++
++ r = value * sd->m;
++ k1 = sd->k & 0x0f;
++ k2 = sd->k >> 4;
++ if (k1 < 8)
++ r += sd->b * exps[k1];
++ else
++ r += sd->b / exps[16 - k1];
++ r *= exps[decplaces(sd)];
++ if (k2 < 8) {
++ if (sd->linear != 7)
++ r *= exps[k2];
++ else
++ /* this will always truncate to 0: r = 1 / (exps[k2] * r); */
++ r = 0;
++ } else {
++ if (sd->linear != 7)
++ r /= exps[16 - k2];
++ else {
++ if (r != 0)
++ /* 1 / x * 10 ** (-m) == 10 ** m / x */
++ r = exps[16 - k2] / r;
++ else
++ r = 0;
++ }
++ }
++
++ return r;
++}
++
++static const char *threshold_text[] = {
++ "upper non-recoverable threshold",
++ "upper critical threshold",
++ "upper non-critical threshold",
++ "lower non-recoverable threshold",
++ "lower critical threshold",
++ "lower non-critical threshold",
++ "positive-going hysteresis",
++ "negative-going hysteresis" /* unused */
++};
++
++/* select two out of the 8 possible readable thresholds, and place indexes into the limits
++ array into lim1 and lim2. Set writable flags */
++static void ipmisensors_select_thresholds(struct sdrdata *sd)
++{
++ u8 capab = sd->capab;
++ u16 mask = sd->thresh_mask;
++ int tmp;
++
++ sd->lim1 = -1;
++ sd->lim2 = -1;
++ sd->lim1_write = 0;
++ sd->lim2_write = 0;
++
++ if (((capab & 0x0c) == 0x04) || /* readable thresholds ? */
++ ((capab & 0x0c) == 0x08)) {
++ /* select upper threshold */
++ if (mask & 0x10) { /* upper crit */
++ sd->lim1 = 1;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x1000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x20) { /* upper non-recov */
++ sd->lim1 = 0;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x2000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x08) { /* upper non-crit */
++ sd->lim1 = 2;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0800))
++ sd->lim1_write = 1;
++ }
++
++ /* select lower threshold */
++ if ((((capab & 0x30) == 0x10) || /* readable ? */
++ ((capab & 0x30) == 0x20)) && /* pos hyst */
++ sd->stype == STYPE_TEMP)
++ sd->lim2 = 6;
++ else if (mask & 0x02) { /* lower crit */
++ sd->lim2 = 4;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0200))
++ sd->lim2_write = 1;
++ } else if (mask & 0x04) { /* lower non-recov */
++ sd->lim2 = 3;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0400))
++ sd->lim2_write = 1;
++ } else if (mask & 0x01) { /* lower non-crit */
++ sd->lim2 = 5;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0100))
++ sd->lim2_write = 1;
++ }
++ }
++
++ /* swap lim1/lim2 if m < 0 or function is 1/x (but not both!) */
++ if ((sd->m < 0 && sd->linear != 7) || (sd->m >= 0 && sd->linear == 7)) {
++ tmp = sd->lim1;
++ sd->lim1 = sd->lim2;
++ sd->lim2 = tmp;
++ }
++
++ if (sd->lim1 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for upper limit\n",
++ threshold_text[sd->lim1]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable upper limit\n");
++
++ if (sd->lim2 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for lower limit\n",
++ threshold_text[sd->lim2]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable lower limit\n");
++}
++
++/************* sysfs callback functions *********/
++static ssize_t show_update_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ return snprintf(buf, 20, "%d\n", aattr->bmc->update_period);
++}
++
++static ssize_t store_update_period(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ aattr->bmc->update_period = simple_strtoul(buf, NULL, 10);;
++ return count;
++};
++
++static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ return snprintf(buf, 20, "%ld\n",
++ conv_val(sattr->sdr->reading, sattr->sdr));
++}
++
++static ssize_t show_sensor_max(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long max = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim1 >= 0)
++ max = conv_val(sattr->sdr->limits[sattr->sdr->lim1],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", max);
++}
++
++static ssize_t show_sensor_min(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long min = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim2 >= 0)
++ min = conv_val(sattr->sdr->limits[sattr->sdr->lim2],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", min);
++};
++
++static ssize_t show_sensor_label(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ u8 label[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ ipmisensors_sprintf(label, sattr->sdr->id, sattr->sdr->string_type,
++ sattr->sdr->id_length);
++ return snprintf(buf, 20, "%s\n", label);
++};
++
++static ssize_t store_sensor_max(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set max on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim1);
++ return count;
++};
++
++static ssize_t store_sensor_min(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set min on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim2);
++ return count;
++};
++
++static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++ return snprintf(buf, 20, "%d\n", aattr->bmc->alarms);
++};
++
++static ssize_t show_name(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return snprintf(buf, 20, "%s\n", driver_data.driver_name);
++};
++
++/* work function to build the sysfs entries using the ipmi sdrs */
++static void ipmisensors_build_sysfs(struct work_struct *work)
++{
++ int temps = 0, volts = 0, currs = 0, fans = 0;
++ struct sdrdata *cursor, *next;
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, sysfs_work);
++
++ /* find and create entries for each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++
++ cursor->attr_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_max_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_min_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ return;
++ }
++ }
++
++ if (cursor->attr_name == NULL || cursor->attr_max_name == NULL
++ || cursor->attr_min_name == NULL
++ || cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "temp%d_input", ++temps);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "temp%d_max", temps);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "temp%d_min", temps);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "temp%d_label", temps);
++ break;
++ case (STYPE_VOLT):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "in%d_input", ++volts);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "in%d_max", volts);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "in%d_min", volts);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "in%d_label", volts);
++ break;
++ case (STYPE_CURR):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "curr%d_input", ++currs);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "curr%d_max", currs);
++ sprintf(cursor->attr_min_name, "curr%d_min", currs);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "curr%d_label", currs);
++ break;
++ case (STYPE_FAN):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "fan%d_input", ++fans);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "fan%d_max", fans);
++ sprintf(cursor->attr_min_name, "fan%d_min", fans);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "fan%d_label", fans);
++ break;
++ default:
++ printk(KERN_INFO "ipmisensors: unkown sensor type\n");
++ continue;
++ }
++
++ cursor->attr.dev_attr.attr.name = cursor->attr_name;
++ cursor->attr.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr.dev_attr.show = show_sensor;
++ cursor->attr.dev_attr.store = NULL;
++ cursor->attr.sdr = cursor;
++
++ cursor->attr_min.dev_attr.attr.name = cursor->attr_min_name;
++ cursor->attr_min.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_min.dev_attr.show = show_sensor_min;
++ cursor->attr_min.sdr = cursor;
++
++ if (cursor->lim2_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_min.dev_attr.store = store_sensor_min;
++ cursor->attr_min.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_min.dev_attr.store = NULL;
++ cursor->attr_min.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ cursor->attr_max.dev_attr.attr.name = cursor->attr_max_name;
++ cursor->attr_max.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_max.dev_attr.show = show_sensor_max;
++ cursor->attr_max.sdr = cursor;
++
++ if (cursor->lim1_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_max.dev_attr.store = store_sensor_max;
++ cursor->attr_max.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_max.dev_attr.store = NULL;
++ cursor->attr_max.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label.dev_attr.attr.name =
++ cursor->attr_label_name;
++ cursor->attr_label.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr_label.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_label.dev_attr.show = show_sensor_label;
++ cursor->attr_label.dev_attr.store = NULL;
++ cursor->attr_label.sdr = cursor;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registering sensor %d: (type 0x%.2x) "
++ "(fmt=%d; m=%d; b=%d; k1=%d; k2=%d; cap=0x%.2x; mask=0x%.4x)\n",
++ cursor->number, cursor->stype, cursor->format, cursor->m,
++ cursor->b, cursor->k & 0xf, cursor->k >> 4,
++ cursor->capab, cursor->thresh_mask);
++
++ if (cursor->id_length > 0) {
++ ipmisensors_sprintf(id, cursor->id, cursor->string_type,
++ cursor->id_length);
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label temp%d \"%s\"\n",
++ temps, id);
++ break;
++ case (STYPE_VOLT):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label in%d \"%s\"\n",
++ volts, id);
++ break;
++ case (STYPE_CURR):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label curr%d \"%s\"\n",
++ currs, id);
++ break;
++ case (STYPE_FAN):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label fan%d \"%s\"\n",
++ fans, id);
++ break;
++ }
++ }
++
++ ipmisensors_select_thresholds(cursor);
++
++ if (cursor->linear != 0 && cursor->linear != 7) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: nonlinear function 0x%.2x unsupported, expect bad results\n",
++ cursor->number, cursor->linear);
++ }
++
++ if ((cursor->format & 0x03) == 0x02) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: 1's complement format unsupported, expect bad results\n",
++ cursor->number);
++ } else if ((cursor->format & 0x03) == 0x03) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: threshold sensor only, no readings available",
++ cursor->number);
++ }
++
++ if (cursor->lim1_write || cursor->lim2_write)
++ cursor->attr.dev_attr.attr.mode = 0644;
++ else
++ cursor->attr.dev_attr.attr.mode = 0444;
++
++ if (device_create_file(bmc->dev, &cursor->attr.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_min.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_max.dev_attr) < 0
++ || (cursor->id_length >
++ 0 ? device_create_file(bmc->dev,
++ &cursor->attr_label.dev_attr) <
++ 0 : 0)
++ ) {
++ printk(KERN_INFO
++ "ipmisensors: sysfs file creation failed for SDR %d (%s).\n",
++ cursor->number, cursor->id);
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++ }
++
++ bmc->alarms_attr.dev_attr.attr.name = "alarms";
++ bmc->alarms_attr.dev_attr.attr.mode = S_IRUGO;
++ bmc->alarms_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->alarms_attr.dev_attr.show = show_alarms;
++ bmc->alarms_attr.dev_attr.store = NULL;
++ bmc->alarms_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->alarms_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'alarms'");
++ return;
++ }
++
++ bmc->name_attr.attr.name = "name";
++ bmc->name_attr.attr.mode = S_IRUGO;
++ bmc->name_attr.attr.owner = THIS_MODULE;
++ bmc->name_attr.show = show_name;
++
++ if (device_create_file(bmc->dev, &bmc->name_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'name'");
++ return;
++ }
++
++ bmc->update_attr.dev_attr.attr.name = "update_period";
++ bmc->update_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ bmc->update_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->update_attr.dev_attr.show = show_update_period;
++ bmc->update_attr.dev_attr.store = store_update_period;
++ bmc->update_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->update_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'update_period'");
++ return;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registered %d temp, %d volt, %d current, %d fan sensors\n",
++ temps, volts, currs, fans);
++
++ /* This completes the initialization. We can now kickoff the
++ * periodic update of the bmc sensor's values by scheduling
++ * the first work.
++ */
++ queue_work(ipmisensors_workqueue, &bmc->update_work.work);
++
++}
++
++/**
++ * Process an SDR response message, save the SDRs we like in the sdr
++ * list for the given BMC.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_sdr_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ u16 record;
++ int type;
++ int stype;
++ int id_length;
++ int i;
++ int ipmi_ver = 0;
++ unsigned char *data;
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct sdrdata *sdr;
++
++ if (msg->data[0] != 0) {
++ /* cut request in half and try again */
++ bmc->ipmi_sdr_partial_size /= 2;
++ if (bmc->ipmi_sdr_partial_size < 8) {
++ printk(KERN_INFO
++ "ipmisensors: IPMI buffers too small, giving up\n");
++ bmc->state = STATE_DONE;
++ return;
++ }
++ printk(KERN_DEBUG
++ "ipmisensors: Reducing SDR request size to %d\n",
++ bmc->ipmi_sdr_partial_size);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ if (bmc->ipmi_sdr_partial_size < IPMI_SDR_SIZE) {
++ if (bmc->rx_msg_data_offset == 0) {
++ memcpy(bmc->rx_msg_data, msg->data,
++ bmc->ipmi_sdr_partial_size + 3);
++ bmc->rx_msg_data_offset =
++ bmc->ipmi_sdr_partial_size + 3;
++ } else {
++ memcpy(bmc->rx_msg_data + bmc->rx_msg_data_offset,
++ msg->data + 3, bmc->ipmi_sdr_partial_size);
++ bmc->rx_msg_data_offset += bmc->ipmi_sdr_partial_size;
++ }
++ if (bmc->rx_msg_data_offset > bmc->rx_msg_data[7] + 7) {
++ /* got last chunk */
++ bmc->rx_msg_data_offset = 0;
++ data = bmc->rx_msg_data;
++ } else {
++ /* get more */
++ record =
++ (bmc->rx_msg_data[4] << 8) | bmc->rx_msg_data[3];
++ ipmisensors_get_sdr(bmc, bmc->resid, record,
++ bmc->rx_msg_data_offset - 3);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ } else {
++ /* got it in one chunk */
++ data = msg->data;
++ }
++
++ bmc->nextrecord = (data[2] << 8) | data[1];
++
++ /* If the ipmi version is 0.9 we have to remap some things.
++ * Yes this is very ugly, but we aren't the ones who
++ * implemented an incomplete spec!
++ */
++ ipmi_ver = data[5];
++
++ type = data[6];
++ /* known SDR type */
++ if (type == 1 || type == 2) {
++ stype = data[(ipmi_ver == 0x90 ? 16 : 15)];
++ /* known sensor type */
++ if (stype <= STYPE_MAX) {
++ if (data[(ipmi_ver == 0x90 ? 17 : 16)] != 0x01) {
++ if (type == 1)
++ ipmisensors_sprintf(id, &data[51],
++ data[50] >> 6,
++ data[50] & 0x1f);
++ else
++ ipmisensors_sprintf(id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 :
++ 35)],
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] >> 6,
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] & 0x1f);
++ printk(KERN_INFO
++ "ipmisensors: skipping non-threshold sensor \"%s\"\n",
++ id);
++ } else {
++ /* add entry to sdrd table */
++ sdr = ipmisensors_new_sdr();
++ if (!sdr) {
++ printk(KERN_ERR
++ "ipmisensors: could not allocate memory for new SDR");
++ return;
++ }
++ sdr->bmc = bmc;
++ sdr->stype = stype;
++ sdr->number = data[10];
++ sdr->capab = data[(ipmi_ver == 0x90 ? 15 : 14)];
++ sdr->thresh_mask =
++ (((u16) data[(ipmi_ver == 0x90 ? 21 : 22)])
++ << 8) | data[21];
++ if (type == 1) {
++ sdr->format =
++ data[(ipmi_ver ==
++ 0x90 ? 22 : 24)] >> 6;
++ sdr->linear =
++ data[(ipmi_ver ==
++ 0x90 ? 25 : 26)] & 0x7f;
++ sdr->m =
++ data[(ipmi_ver == 0x90 ? 26 : 27)];
++ sdr->m |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 27 : 28)]
++ & 0xc0)) << 2;
++ if (sdr->m & 0x0200) {
++ /* sign extend */
++ sdr->m |= 0xfc00;
++ }
++ sdr->b =
++ data[(ipmi_ver == 0x90 ? 28 : 29)];
++ sdr->b |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 29 : 30)]
++ & 0xc0)) << 2;
++ if (sdr->b & 0x0200) {
++ /* sign extend */
++ sdr->b |= 0xfc00;
++ }
++ sdr->k =
++ data[(ipmi_ver == 0x90 ? 31 : 32)];
++ sdr->nominal =
++ data[(ipmi_ver == 0x90 ? 33 : 34)];
++ for (i = 0; i < SDR_LIMITS; i++) {
++ /* assume readable */
++ sdr->limits[i] =
++ data[(ipmi_ver ==
++ 0x90 ? 40 : 39) + i];
++ }
++ sdr->string_type = data[50] >> 6;
++ id_length = data[50] & 0x1f;
++ memcpy(sdr->id, &data[51], id_length);
++ sdr->id_length = id_length;
++ } else {
++ sdr->m = 1;
++ sdr->b = 0;
++ sdr->k = 0;
++ sdr->string_type =
++ data[(ipmi_ver ==
++ 0x90 ? 29 : 34)] >> 6;
++ id_length = data[34] & 0x1f;
++ if (id_length > 0) {
++ memcpy(sdr->id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 : 35)],
++ id_length);
++ }
++ sdr->id_length = id_length;
++ /* limits?? */
++ if (ipmi_ver == 0x90) {
++ memcpy(sdr->id,
++ &data[30], id_length);
++ sdr->id_length = id_length;
++ }
++ }
++ ipmisensors_add_sdr(bmc, sdr);
++ }
++ }
++ /* peek at the other SDR types */
++ } else if (type == 0x10 || type == 0x11 || type == 0x12) {
++ ipmisensors_sprintf(id, data + 19, data[18] >> 6,
++ data[18] & 0x1f);
++ if (type == 0x10) {
++ printk(KERN_INFO
++ "ipmisensors: Generic Device acc=0x%x; slv=0x%x; lun=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[13], id);
++ } else if (type == 0x11) {
++ printk(KERN_INFO
++ "ipmisensors: FRU Device acc=0x%x; slv=0x%x; log=0x%x; ch=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[11], data[13],
++ id);
++ } else {
++ printk(KERN_INFO
++ "ipmisensors: Mgmt Ctllr Device slv=0x%x; \"%s\"\n",
++ data[8], id);
++ }
++ } else if (type == 0x14) {
++ printk(KERN_INFO
++ "ipmisensors: Message Channel Info Records:\n");
++ for (i = 0; i < 8; i++) {
++ printk(KERN_INFO "ipmisensors: Channel %d info 0x%x\n",
++ i, data[9 + i]);
++ }
++ } else {
++ printk(KERN_INFO "ipmisensors: Skipping SDR type 0x%x\n", type);
++ }
++ if (ipmi_ver != 0x90) {
++ if (bmc->nextrecord >= 6224) {
++ /*YJ stop sensor scan on poweredge 1750 */
++ bmc->nextrecord = 0xffff;
++ }
++ }
++
++ if (bmc->nextrecord == 0xFFFF) {
++ if (bmc->sdr_count == 0) {
++ printk(KERN_INFO
++ "ipmisensors: No recognized sensors found.\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_INFO "ipmisensors: all sensors detected\n");
++ bmc->state = STATE_SYSTABLE;
++
++ /* Schedule sysfs build/registration work */
++ INIT_WORK(&bmc->sysfs_work, ipmisensors_build_sysfs);
++ queue_work(ipmisensors_workqueue, &bmc->sysfs_work);
++ }
++ } else {
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ }
++}
++
++/**
++ * Process incoming messages based on internal state
++ *
++ * @bmc: the bmc the message is from.
++ * @msg: the ipmi message to process.
++ */
++static void ipmisensors_rcv_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ switch (bmc->state) {
++ case STATE_INIT:
++ case STATE_RESERVE:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got first resid 0x%.4x\n",
++ bmc->resid);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_SDR:
++ case STATE_SDRPARTIAL:
++ ipmisensors_rcv_sdr_msg(bmc, msg);
++ break;
++
++ case STATE_READING:
++ ipmisensors_rcv_reading_msg(bmc, msg);
++ break;
++
++ case STATE_UNCANCEL:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got new resid 0x%.4x\n",
++ bmc->resid);
++
++ bmc->rx_msg_data_offset = 0;
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_DONE:
++ case STATE_SYSTABLE:
++ break;
++ default:
++ bmc->state = STATE_INIT;
++ }
++}
++
++/**
++ * Callback to handle a received IPMI message from a given BMC.
++ *
++ * @msg: the received message.
++ * @handler_data: a pointer to the particular bmc ipmisensors_bmc_data struct.
++ */
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data)
++{
++ struct ipmisensors_bmc_data *bmc =
++ (struct ipmisensors_bmc_data *)user_msg_data;
++
++ if (msg->msg.data[0] != 0)
++ printk(KERN_WARNING
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x\n",
++ msg->msg.data[0], msg->msg.netfn, msg->msg.cmd);
++
++ if (bmc != NULL && ipmisensors_intf_registered(bmc->interface_id)) {
++ if (bmc->state == STATE_SDR &&
++ msg->msg.data[0] == IPMI_INVALID_RESERVATION_ID) {
++ /* reservation cancelled, get new resid */
++ if (++bmc->errorcount > 275) {
++ printk(KERN_ERR
++ "ipmisensors: Too many reservations cancelled, giving up\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_DEBUG
++ "ipmisensors: resid 0x%04x cancelled, getting new one\n",
++ bmc->resid);
++
++ ipmisensors_reserve_sdr(bmc);
++ bmc->state = STATE_UNCANCEL;
++ }
++ } else if (msg->msg.data[0] != IPMI_CC_NO_ERROR &&
++ msg->msg.data[0] != IPMI_ERR_RETURNING_REQ_BYTES &&
++ msg->msg.data[0] != IPMI_ERR_PROVIDING_RESPONSE) {
++ printk(KERN_ERR
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x; state = %d; probably fatal.\n",
++ msg->msg.data[0], msg->msg.netfn & 0xfe,
++ msg->msg.cmd, bmc->state);
++ } else {
++ printk(KERN_DEBUG "ipmisensors: received message\n");
++ ipmisensors_rcv_msg(bmc, &msg->msg);
++ }
++
++ } else {
++ printk(KERN_WARNING
++ "ipmisensors: Response for non-registered BMC\n");
++ if (bmc != NULL)
++ printk(KERN_DEBUG "ipmisensors: BMC ID: %d\n",
++ bmc->interface_id);
++ else
++ printk(KERN_DEBUG "ipmisensors: BMC NULL!\n");
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++/****** IPMI Interface Initialization ******/
++
++/**
++ * Return true if the given ipmi interface has been registered.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static int ipmisensors_intf_registered(int ipmi_intf)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Return true if the given BMC has been registered.
++ *
++ * @bmc: The BMC device.
++ */
++static int ipmisensors_bmc_registered(struct device *bmc)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->dev == bmc) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Register new IPMI BMC interface. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address)
++{
++ int error;
++
++ /* allocate a new ipmisensors_bmc_data struct */
++
++ struct ipmisensors_bmc_data *bmc = (struct ipmisensors_bmc_data *)
++ kmalloc(sizeof(struct ipmisensors_bmc_data), GFP_KERNEL);
++
++ /* initialize members */
++ INIT_LIST_HEAD(&bmc->sdrs);
++ bmc->interface_id = ipmi_intf;
++
++ bmc->address = *address;
++
++ bmc->sdr_count = 0;
++ bmc->msgid = 0;
++ bmc->ipmi_sdr_partial_size = IPMI_CHUNK_SIZE;
++ bmc->state = STATE_INIT;
++ bmc->errorcount = 0;
++ bmc->rx_msg_data_offset = 0;
++ bmc->dev = ipmi_get_bmcdevice(ipmi_intf);
++
++ /* default to 3 second min update interval */
++ bmc->update_period = 3;
++
++ if (bmc->dev == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error, couldn't get BMC device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Create IPMI messaging interface user */
++ error = ipmi_create_user(bmc->interface_id, &driver_data.ipmi_hndlrs,
++ bmc, &bmc->user);
++ if (error < 0) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register user with ipmi interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC as a HWMON class device */
++ bmc->class_dev = hwmon_device_register(bmc->dev);
++
++ if (IS_ERR(bmc->class_dev)) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register hwmon class device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC in the driver */
++ if (ipmisensors_bmc_registered(bmc->dev)) {
++ printk(KERN_ERR
++ "ipmisensors: BMC on interface %d already registered\n",
++ bmc->interface_id);
++ hwmon_device_unregister(bmc->class_dev);
++ kfree(bmc);
++ return;
++ }
++
++ ipmi_get_version(bmc->user, &bmc->ipmi_version_major,
++ &bmc->ipmi_version_minor);
++
++ /* finally add the new bmc data to the bmc data list */
++ list_add_tail(&bmc->list, &driver_data.bmc_data);
++ driver_data.interfaces++;
++
++ printk(KERN_INFO
++ "ipmisensors: Registered IPMI %d.%d BMC over interface %d\n",
++ bmc->ipmi_version_major,
++ bmc->ipmi_version_minor, bmc->interface_id);
++
++ /* Send a reserve SDR command to the bmc */
++ ipmisensors_reserve_sdr(bmc);
++
++ /* initialize the bmc's update work struct */
++ INIT_DELAYED_WORK(&bmc->update_work, ipmisensors_update_bmc);
++}
++
++/**
++ * Callback for when an IPMI BMC is gone. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_unregister_bmc(int ipmi_intf)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ list_del(&cursor->list);
++ printk(KERN_DEBUG
++ "ipmisensors: cancelling queued work\n");
++ /* cancel update work queued for this bmc */
++ cancel_delayed_work(&cursor->update_work);
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev,
++ &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev,
++ &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ driver_data.interfaces--;
++ }
++ }
++
++}
++
++/**
++ * Unregister all registered bmcs.
++ */
++static void ipmisensors_unregister_bmc_all(void)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ list_del(&cursor->list);
++
++ /* cancel update work queued for this bmc */
++ printk(KERN_DEBUG "ipmisensors: cancelling queued work\n");
++ cancel_delayed_work(&cursor->update_work);
++
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev, &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev, &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ }
++
++ driver_data.interfaces = 0;
++}
++
++/**
++ * Callback for when a new IPMI SMI type interface is found.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_new_smi(int if_num, struct device *dev)
++{
++ struct ipmi_addr smi_address = {
++ IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
++ IPMI_BMC_CHANNEL,
++ {0},
++ };
++
++ /* calls the generic new interface function */
++ ipmisensors_register_bmc(if_num, &smi_address);
++}
++
++/**
++ * Callback for when an exisiting IPMI SMI type interface is gone.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_smi_gone(int if_num)
++{
++ if (driver_data.interfaces > 0) {
++ ipmisensors_unregister_bmc(if_num);
++ }
++}
++
++/**
++ * Initialize the module.
++ */
++static int __init ipmisensors_init(void)
++{
++ int error;
++ printk(KERN_INFO "ipmisensors - IPMI BMC sensors interface\n");
++
++ /* init cache managers */
++ driver_data.sdrdata_cache =
++ kmem_cache_create("ipmisensors_sdrdata", sizeof(struct sdrdata), 0,
++ 0, NULL, NULL);
++ driver_data.sysfsattr_cache =
++ kmem_cache_create("ipmisensors_sysfsattr",
++ sizeof(struct ipmisensors_device_attribute), 0, 0,
++ NULL, NULL);
++
++ if (!driver_data.sdrdata_cache || !driver_data.sysfsattr_cache) {
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++ return -ENOMEM;
++ }
++
++ /* register IPMI interface callback(s) */
++ error = ipmi_smi_watcher_register(&driver_data.smi_watcher);
++ if (error) {
++ printk(KERN_WARNING
++ "ipmisensors: can't register smi watcher\n");
++ return error;
++ }
++
++ /* create work queue, keep it simple, single-threaded */
++ ipmisensors_workqueue =
++ create_singlethread_workqueue("ipmisensors_workqueue");
++
++ return 0;
++}
++
++/**
++ * Cleanup
++ */
++static void ipmisensors_cleanup(void)
++{
++ /* start cleanup */
++ cleanup = 1;
++
++ /* unregister bmcs */
++ printk(KERN_DEBUG "ipmisensors: unregister bmcs\n");
++ ipmi_smi_watcher_unregister(&driver_data.smi_watcher);
++ ipmisensors_unregister_bmc_all();
++
++ /* flush & destroy work queue */
++ printk(KERN_DEBUG "ipmisensors: destroy workqueue\n");
++ flush_workqueue(ipmisensors_workqueue);
++ destroy_workqueue(ipmisensors_workqueue);
++
++ /* remove cache managers */
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++}
++
++/**
++ * Cleanup and exit the module
++ */
++static void __exit ipmisensors_exit(void)
++{
++ ipmisensors_cleanup();
++ printk(KERN_DEBUG "ipmisensors: cleanup finished\n");
++}
++
++MODULE_AUTHOR("Yani Ioannou <yani.ioannou@gmail.com>");
++MODULE_DESCRIPTION("IPMI BMC sensors");
++MODULE_LICENSE("GPL");
++
++module_init(ipmisensors_init);
++module_exit(ipmisensors_exit);
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.h linux-2.6.20.3/drivers/hwmon/ipmisensors.h
+--- linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/ipmisensors.h 2007-03-14 14:41:23.000000000 +0100
+@@ -0,0 +1,240 @@
++/*
++ * ipmisensors.h - lm_sensors interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/ipmi.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++
++/* SDR defs */
++#define STYPE_TEMP 0x01
++#define STYPE_VOLT 0x02
++#define STYPE_CURR 0x03
++#define STYPE_FAN 0x04
++
++#define SDR_LIMITS 8
++#define SDR_MAX_ID_LENGTH 16
++#define SDR_MAX_UNPACKED_ID_LENGTH ((SDR_MAX_ID_LENGTH * 4 / 3) + 2)
++
++/* the last sensor type we are interested in */
++#define STYPE_MAX 4
++
++#define IPMI_SDR_SIZE 67
++#define IPMI_CHUNK_SIZE 16
++
++#define MAX_FILENAME_LENGTH 30
++
++struct ipmisensors_device_attribute {
++ struct device_attribute dev_attr;
++ struct sdrdata *sdr;
++};
++#define to_ipmisensors_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_device_attribute, dev_attr)
++
++#define IPMISENSORS_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
++struct ipmisensors_attribute sensor_dev_attr_##_name = { \
++ .dev_attr = __ATTR(_name,_mode,_show,_store), \
++ .index = _index, \
++}
++
++struct ipmisensors_bmc_device_attribute {
++ struct device_attribute dev_attr;
++ struct ipmisensors_bmc_data *bmc;
++};
++#define to_ipmisensors_bmc_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_bmc_device_attribute, dev_attr)
++
++/**
++ * &struct_sdrdata stores the IPMI Sensor Data Record (SDR) data, as recieved from the BMC, along with the corresponding sysfs attributes
++ */
++struct sdrdata {
++ struct list_head list;
++ /* retrieved from SDR, not expected to change */
++ /* Sensor Type Code */
++ u8 stype;
++ u8 number;
++ /* Sensor Capability Code */
++ u8 capab;
++ u16 thresh_mask;
++ u8 format;
++ u8 linear;
++ s16 m;
++ s16 b;
++ u8 k;
++ u8 nominal;
++ u8 limits[SDR_LIMITS];
++ /* index into limits for reported upper and lower limit */
++ int lim1, lim2;
++ u8 lim1_write, lim2_write;
++ u8 string_type;
++ u8 id_length;
++ u8 id[SDR_MAX_ID_LENGTH];
++ /* retrieved from reading */
++ u8 reading;
++ u8 status;
++ u8 thresholds;
++ /* sensor's bmc */
++ struct ipmisensors_bmc_data *bmc;
++ /* sysfs entries */
++ struct ipmisensors_device_attribute attr;
++ char *attr_name;
++ struct ipmisensors_device_attribute attr_min;
++ char *attr_min_name;
++ struct ipmisensors_device_attribute attr_max;
++ char *attr_max_name;
++ struct ipmisensors_device_attribute attr_label;
++ char *attr_label_name;
++
++};
++
++/**
++ * &struct_ipmisensors_data stores the data for the ipmisensors driver.
++ */
++struct ipmisensors_data {
++ /* Driver struct */
++ char *driver_name;
++
++ /* Linked list of ipmisensors_bmc_data structs, one for each BMC */
++ struct list_head bmc_data;
++
++ /* Number of ipmi interfaces (and hence ipmisensors_data structs). */
++ int interfaces;
++
++ /* IPMI kernel interface - SMI watcher */
++ struct ipmi_smi_watcher smi_watcher;
++
++ /* IPMI kernel interface - user handlers */
++ struct ipmi_user_hndl ipmi_hndlrs;
++
++ /* Cache manager for sdrdata cache */
++ struct kmem_cache *sdrdata_cache;
++
++ /* Cache manager for ipmi_sensor_device_attribute cache */
++ struct kmem_cache *sysfsattr_cache;
++};
++
++/**
++ * &states: enumeration of state codes for a bmc specific ipmisensors
++ */
++enum states {
++ STATE_INIT,
++ STATE_RESERVE,
++ STATE_SDR,
++ STATE_SDRPARTIAL,
++ STATE_READING,
++ STATE_UNCANCEL,
++ STATE_SYSTABLE,
++ STATE_DONE
++};
++
++/**
++ * &struct_ipmisensors_bmc_data stores the data for a particular IPMI BMC.
++ */
++struct ipmisensors_bmc_data {
++ struct list_head list;
++
++ /* The IPMI interface number */
++ int interface_id;
++
++ /* The IPMI address */
++ struct ipmi_addr address;
++
++ /* List of sdrdata structs (sdrs) recieved from the BMC */
++ struct list_head sdrs;
++
++ /* Count of the number of sdrs stored in the sdr list */
++ int sdr_count;
++
++ /* next message id */
++ int msgid;
++
++ /* The ipmi interface 'user' used to access this particular bmc */
++ ipmi_user_t user;
++
++ /* BMC IPMI Version (major) */
++ unsigned char ipmi_version_major;
++
++ /* BMC IPMI Version (minor) */
++ unsigned char ipmi_version_minor;
++
++ /* The size of the SDR request message */
++ int ipmi_sdr_partial_size;
++
++ /* transmit message buffer */
++ struct kernel_ipmi_msg tx_message;
++
++ /* ipmi transmited data buffer */
++ unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; /* why the +50 in bmcsensors? */
++
++ /* ipmi recieved data buffer */
++ unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH + 50];
++
++ /* current recieve buffer offset */
++ int rx_msg_data_offset;
++
++ /* The id of then next SDR record to read during update cycle */
++ u16 nextrecord;
++
++ /* BMC SDR Reservation ID */
++ u16 resid;
++
++ /* Alarm status */
++ u8 alarms;
++
++ /* The cumalative error count for this bmc */
++ int errorcount;
++
++ /* The current state of this bmc w.r.t. ipmisensors (see enum states) */
++ int state;
++
++ /* The current sdr for which a reading is pending */
++ struct sdrdata *current_sdr;
++
++ /* The BMC's device struct */
++ struct device *dev;
++
++ /* hwmon class device */
++ struct class_device *class_dev;
++
++ /* hwmon device name */
++ struct device_attribute name_attr;
++
++ /* alarms attribute */
++ struct ipmisensors_bmc_device_attribute alarms_attr;
++
++ /* update_period attribute */
++ struct ipmisensors_bmc_device_attribute update_attr;
++
++ /* lower bound on time between updates (in seconds) */
++ unsigned int update_period;
++
++ /* semaphore used to do a headcount of the SDR readings we are waiting
++ * on in a given bmc update */
++ struct semaphore update_semaphore;
++
++ /* bmc's work struct for updating sensors */
++ struct delayed_work update_work;
++
++ /* bmc's work struct for building the sysfs workqueue */
++ struct work_struct sysfs_work;
++};
+diff -rduNp linux-2.6.20.3.orig/include/linux/ipmi.h linux-2.6.20.3/include/linux/ipmi.h
+--- linux-2.6.20.3.orig/include/linux/ipmi.h 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/include/linux/ipmi.h 2007-03-14 14:23:02.000000000 +0100
+@@ -300,6 +300,9 @@ int ipmi_create_user(unsigned int
+ safe, too. */
+ int ipmi_destroy_user(ipmi_user_t user);
+
++/* Get the IPMI BMC's device struct */
++struct device *ipmi_get_bmcdevice(int ipmi_intf);
++
+ /* Get the IPMI version of the BMC we are talking to. */
+ void ipmi_get_version(ipmi_user_t user,
+ unsigned char *major,
+diff -rduNp linux-2.6.20.3.orig/include/linux/ipmi_msgdefs.h linux-2.6.20.3/include/linux/ipmi_msgdefs.h
+--- linux-2.6.20.3.orig/include/linux/ipmi_msgdefs.h 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/include/linux/ipmi_msgdefs.h 2007-03-14 14:23:02.000000000 +0100
+@@ -45,6 +45,7 @@
+
+ #define IPMI_NETFN_APP_REQUEST 0x06
+ #define IPMI_NETFN_APP_RESPONSE 0x07
++#define IPMI_GET_DEVICE_GUID_CMD 0x08
+ #define IPMI_GET_DEVICE_ID_CMD 0x01
+ #define IPMI_COLD_RESET_CMD 0x02
+ #define IPMI_WARM_RESET_CMD 0x03
+@@ -57,6 +58,11 @@
+ #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
+ #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
+ #define IPMI_GET_CHANNEL_INFO_CMD 0x42
++#define IPMI_RESERVE_SDR 0x22
++#define IPMI_GET_SDR 0x23
++#define IPMI_GET_SENSOR_STATE_READING 0x2D
++#define IPMI_SET_SENSOR_HYSTERESIS 0x24
++#define IPMI_SET_SENSOR_THRESHOLD 0x26
+
+ #define IPMI_NETFN_STORAGE_REQUEST 0x0a
+ #define IPMI_NETFN_STORAGE_RESPONSE 0x0b
+@@ -79,10 +85,13 @@
+ #define IPMI_NODE_BUSY_ERR 0xc0
+ #define IPMI_INVALID_COMMAND_ERR 0xc1
+ #define IPMI_TIMEOUT_ERR 0xc3
++#define IPMI_INVALID_RESERVATION_ID 0xc5
+ #define IPMI_ERR_MSG_TRUNCATED 0xc6
+ #define IPMI_REQ_LEN_INVALID_ERR 0xc7
+ #define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
+ #define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
++#define IPMI_ERR_RETURNING_REQ_BYTES 0xca
++#define IPMI_ERR_PROVIDING_RESPONSE 0xce
+ #define IPMI_LOST_ARBITRATION_ERR 0x81
+ #define IPMI_BUS_ERR 0x82
+ #define IPMI_NAK_ON_WRITE_ERR 0x83
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.21.5-007-ipmisensors-20070314-1214.patch b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.21.5-007-ipmisensors-20070314-1214.patch
new file mode 100644
index 0000000000..aca57c37b0
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.21.5-007-ipmisensors-20070314-1214.patch
@@ -0,0 +1,1914 @@
+diff -rduNp linux-2.6.20.3.orig/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.20.3/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.20.3.orig/drivers/char/ipmi/ipmi_msghandler.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/char/ipmi/ipmi_msghandler.c 2007-03-14 14:23:02.000000000 +0100
+@@ -1954,6 +1954,24 @@ static void remove_proc_entries(ipmi_smi
+ #endif /* CONFIG_PROC_FS */
+ }
+
++/*
++ * Retrieves the bmc_device struct for a given ipmi interface number (or NULL if none).
++ */
++struct device *ipmi_get_bmcdevice(int if_num)
++{
++ ipmi_smi_t intf;
++ mutex_lock(&ipmi_interfaces_mutex);
++ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
++ if (intf->intf_num == if_num){
++ mutex_unlock(&ipmi_interfaces_mutex);
++ return &intf->bmc->dev->dev;
++ }
++ }
++ mutex_unlock(&ipmi_interfaces_mutex);
++
++ return NULL;
++}
++
+ static int __find_bmc_guid(struct device *dev, void *data)
+ {
+ unsigned char *id = data;
+@@ -4183,3 +4201,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN);
+ EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+ EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+ EXPORT_SYMBOL(ipmi_free_recv_msg);
++EXPORT_SYMBOL(ipmi_get_bmcdevice);
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/Kconfig linux-2.6.20.3/drivers/hwmon/Kconfig
+--- linux-2.6.20.3.orig/drivers/hwmon/Kconfig 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/Kconfig 2007-03-14 14:23:02.000000000 +0100
+@@ -218,6 +218,16 @@ config SENSORS_GL520SM
+ This driver can also be built as a module. If so, the module
+ will be called gl520sm.
+
++config SENSORS_IPMI
++ tristate "IPMI Hardware Monitoring Support"
++ depends on HWMON && IPMI_HANDLER && EXPERIMENTAL
++ help
++ If you say yes here you get support for sensors monitored by
++ an IPMI baseboard management controller (BMC).
++
++ This driver can also be built as a module. If so, the module
++ will be called ipmisensors.
++
+ config SENSORS_IT87
+ tristate "ITE IT87xx and compatibles"
+ depends on HWMON && I2C
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/Makefile linux-2.6.20.3/drivers/hwmon/Makefile
+--- linux-2.6.20.3.orig/drivers/hwmon/Makefile 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/Makefile 2007-03-14 14:23:02.000000000 +0100
+@@ -28,6 +28,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
+ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
++obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o
+ obj-$(CONFIG_SENSORS_IT87) += it87.o
+ obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
+ obj-$(CONFIG_SENSORS_LM63) += lm63.o
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.c linux-2.6.20.3/drivers/hwmon/ipmisensors.c
+--- linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/ipmisensors.c 2007-03-14 14:44:42.000000000 +0100
+@@ -0,0 +1,1552 @@
++/*
++ * ipmisensors.c - lm-sensors/hwmon interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/init.h>
++#include <linux/module.h>
++#include <linux/param.h>
++#include <linux/hwmon.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/device.h>
++#include <linux/hwmon.h>
++
++#include "ipmisensors.h"
++
++/****** Function Prototypes ******/
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg);
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc);
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset);
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index);
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr);
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data);
++static int ipmisensors_intf_registered(int ipmi_intf);
++static int ipmisensors_bmc_registered(struct device *bmc);
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address);
++static void ipmisensors_unregister_bmc(int ipmi_intf);
++static void ipmisensors_unregister_bmc_all(void);
++static void ipmisensors_new_smi(int if_num, struct device *dev);
++static void ipmisensors_smi_gone(int if_num);
++static void ipmisensors_update_bmc(struct work_struct *);
++static void ipmisensors_cleanup(void);
++
++/****** Static Vars ******/
++
++/* set when module is being removed */
++static int cleanup = 0;
++
++/* ipmisensors driver data */
++static struct ipmisensors_data driver_data = {
++ .driver_name = "bmc",
++ .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data),
++ .interfaces = 0,
++ .smi_watcher = {
++ .owner = THIS_MODULE,
++ .new_smi = ipmisensors_new_smi,
++ .smi_gone = ipmisensors_smi_gone,
++ },
++ .ipmi_hndlrs = {
++ .ipmi_recv_hndl = ipmisensors_msg_handler,
++ },
++};
++
++/* sensor refresh workqueue */
++static struct workqueue_struct *ipmisensors_workqueue;
++
++/****** SDR List Functions ******/
++/**
++ * Creates a new sdrdata struct, or returns NULL if insufficient memory.
++ */
++static struct sdrdata *ipmisensors_new_sdr(void)
++{
++ struct sdrdata *sdr;
++
++ sdr = kmem_cache_alloc(driver_data.sdrdata_cache, GFP_ATOMIC);
++ if (sdr) {
++ memset(sdr, 0, sizeof(struct sdrdata));
++ } else {
++ printk(KERN_ERR
++ "ipmisensors: Couldn't allocate memory for new SDR\n");
++ }
++
++ return sdr;
++}
++
++/**
++ * Adds the given sdrdata struct to the given bmc's SDR list.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static inline void ipmisensors_add_sdr(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ list_add(&sdr->list, &bmc->sdrs);
++ printk(KERN_DEBUG
++ "ipmisensors: SDR %d: type 0x%02x (%s)\n",
++ bmc->sdr_count, sdr->stype, sdr->id);
++ bmc->sdr_count++;
++}
++
++/**
++ * Cleanup the sdr list for the given BMC.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_sdr_cleanup(struct ipmisensors_bmc_data *bmc)
++{
++ struct sdrdata *cursor, *next;
++
++ /* find and free each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ device_remove_file(bmc->dev, &cursor->attr.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_min.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_max.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_label.dev_attr);
++
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++
++ list_del(&cursor->list);
++ kmem_cache_free(driver_data.sdrdata_cache, cursor);
++ }
++}
++
++/* worker function for workqueue ipmisensors_workqueue */
++static void ipmisensors_update_bmc(struct work_struct *work)
++{
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, update_work.work);
++
++ /* don't start an update cycle if one already in progress */
++ if (bmc->state != STATE_READING) {
++ struct sdrdata *cursor, *next;
++ bmc->state = STATE_READING;
++ printk(KERN_DEBUG "ipmisensors: starting update\n");
++
++ /* init semaphore to 1 for update cycle */
++ sema_init(&bmc->update_semaphore, 1);
++
++ /* update each sdr reading */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ ipmisensors_get_reading(bmc, cursor);
++ }
++ }
++
++ /* wait for readings (need timeout?) */
++ down_interruptible(&bmc->update_semaphore);
++
++ printk(KERN_DEBUG "ipmisensors: update complete\n");
++
++ bmc->state = STATE_DONE;
++
++ /* if the module isn't cleaning up, schedule another update */
++ if (!cleanup)
++ queue_delayed_work(ipmisensors_workqueue, &bmc->update_work,
++ bmc->update_period * HZ);
++}
++
++/****** IPMI Message Sending ******/
++
++/**
++ * Send a message to the IPMI BMC
++ *
++ * @bmc: the bmc to send the message to.
++ * @msgid: the message id to use.
++ * @msg: the ipmi message structure.
++ */
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg)
++{
++ if (msg->data == NULL)
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x\n", msg->cmd);
++ else
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x 0x%x 0x%x\n",
++ msg->cmd, msg->data[0], msg->data[1]);
++
++ /* This should be ipmi_request, but Corey had to remove
++ * that due to it being unused at the moment, as soon as
++ * this makes it into the kernel we should request it be re-instated.
++ */
++ ipmi_request_settime(bmc->user, &bmc->address, msgid, msg, bmc, 0,
++ -1, 0);
++}
++
++/**
++ * Compose and send a "reserve SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_RESERVE_SDR;
++ bmc->tx_message.data_len = 0;
++ bmc->tx_message.data = NULL;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Componse and send a "get SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @res_id:
++ * @record:
++ * @offset:
++ */
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset)
++{
++ printk(KERN_DEBUG "ipmisensors: Get SDR 0x%x 0x%x 0x%x\n",
++ res_id, record, offset);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SDR;
++ bmc->tx_message.data_len = 6;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = res_id & 0xff;
++ bmc->tx_msg_data[1] = res_id >> 8;
++ bmc->tx_msg_data[2] = record & 0xff;
++ bmc->tx_msg_data[3] = record >> 8;
++ bmc->tx_msg_data[4] = offset;
++ bmc->tx_msg_data[5] = bmc->ipmi_sdr_partial_size;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "set sensor threshold" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @id: the ipmi id number of the sensor.
++ * @value: the new value for the threshold.
++ * @lim_index: the index in the lim[] array for which this value applies.
++ */
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index)
++{
++ int i;
++
++ printk(KERN_DEBUG "ipmisensors: Set SDR Threshold %d %d %d\n",
++ number, value, lim_index);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_SET_SENSOR_THRESHOLD;
++ bmc->tx_message.data_len = 8;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = number & 0xff;
++ bmc->tx_msg_data[1] = 0x01 << lim_index;
++
++ if (lim_index > 5 || lim_index < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Error - ipmisensors_set_sensor_threshold given invalid lim_index\n");
++ return;
++ }
++
++ for (i = 2; i < 8; i++)
++ bmc->tx_msg_data[i] = 0x00;
++
++ bmc->tx_msg_data[lim_index] = value && 0xff;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "get sensor reading" message for the given sdr.
++ *
++ * @bmc: the bmc to send the message to.
++ * @sdr: the sdr of the sensor to get the reading for.
++ */
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SENSOR_STATE_READING;
++ bmc->tx_message.data_len = 1;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = sdr->number;
++ bmc->current_sdr = sdr;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++ down_interruptible(&bmc->update_semaphore);
++}
++
++/****** IPMI Message Receiving ******/
++
++/**
++ * Process an sensor reading response message.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_reading_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ struct sdrdata *sdr = bmc->current_sdr;
++
++ if (sdr == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error ipmisensors_rcv_reading with NULL sdr\n");
++ return;
++ }
++
++ sdr->reading = msg->data[1];
++ sdr->status = msg->data[2];
++ sdr->thresholds = msg->data[3];
++
++ printk(KERN_DEBUG "ipmisensors: sensor %d (type %d) reading %d\n",
++ sdr->number, sdr->stype, msg->data[1]);
++
++ up(&bmc->update_semaphore);
++}
++
++/**
++ * Unpack based on string type, convert to normal, null terminate.
++ */
++static void ipmisensors_sprintf(u8 * to, u8 * from, u8 type, u8 length)
++{
++ static const u8 *bcdplus = "0123456789 -.:,_";
++ int i;
++
++ switch (type) {
++ case 0: /* unicode */
++ for (i = 0; i < length; i++)
++ *to++ = (*from++ & 0x7f);
++ *to = 0;
++ break;
++ case 1: /* BCD Plus */
++ for (i = 0; i < length; i++)
++ *to++ = bcdplus[*from++ & 0x0f];
++ *to = 0;
++ break;
++ case 2: /* packed ascii *//* if not a mult. of 3 this will run over */
++ for (i = 0; i < length; i += 3) {
++ *to++ = *from & 0x3f;
++ *to++ = *from >> 6 | ((*(from+1) & 0xf) << 2);
++ from++;
++ *to++ = *from >> 4 | ((*(from+1) & 0x3) << 4);
++ from++;
++ *to++ = (*from++ >> 2) & 0x3f;
++ }
++ *to = 0;
++ break;
++ case 3: /* normal */
++ if (length > 1)
++ memcpy(to, from, length);
++ to[length] = 0;
++ break;
++ }
++}
++
++/* IPMI V1.5 Section 30 */
++static const int exps[] =
++ { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
++
++/* Return 0 for fan, 2 for temp, 3 for voltage
++ We could make it variable based on the accuracy (= log10(m * 10**k2));
++ this would work for /proc output, however libsensors resolution
++ is statically set in lib/chips.c */
++static int decplaces(struct sdrdata *sd)
++{
++ switch (sd->stype) {
++ case STYPE_TEMP:
++ return 2;
++ case STYPE_CURR:
++ case STYPE_VOLT:
++ return 3;
++ case STYPE_FAN:
++ default:
++ return 0;
++ }
++}
++
++/* convert a raw value to a reading. IMPI V1.5 Section 30 */
++static long conv_val(int value, struct sdrdata *sd)
++{
++ u8 k1, k2;
++ long r;
++
++ r = value * sd->m;
++ k1 = sd->k & 0x0f;
++ k2 = sd->k >> 4;
++ if (k1 < 8)
++ r += sd->b * exps[k1];
++ else
++ r += sd->b / exps[16 - k1];
++ r *= exps[decplaces(sd)];
++ if (k2 < 8) {
++ if (sd->linear != 7)
++ r *= exps[k2];
++ else
++ /* this will always truncate to 0: r = 1 / (exps[k2] * r); */
++ r = 0;
++ } else {
++ if (sd->linear != 7)
++ r /= exps[16 - k2];
++ else {
++ if (r != 0)
++ /* 1 / x * 10 ** (-m) == 10 ** m / x */
++ r = exps[16 - k2] / r;
++ else
++ r = 0;
++ }
++ }
++
++ return r;
++}
++
++static const char *threshold_text[] = {
++ "upper non-recoverable threshold",
++ "upper critical threshold",
++ "upper non-critical threshold",
++ "lower non-recoverable threshold",
++ "lower critical threshold",
++ "lower non-critical threshold",
++ "positive-going hysteresis",
++ "negative-going hysteresis" /* unused */
++};
++
++/* select two out of the 8 possible readable thresholds, and place indexes into the limits
++ array into lim1 and lim2. Set writable flags */
++static void ipmisensors_select_thresholds(struct sdrdata *sd)
++{
++ u8 capab = sd->capab;
++ u16 mask = sd->thresh_mask;
++ int tmp;
++
++ sd->lim1 = -1;
++ sd->lim2 = -1;
++ sd->lim1_write = 0;
++ sd->lim2_write = 0;
++
++ if (((capab & 0x0c) == 0x04) || /* readable thresholds ? */
++ ((capab & 0x0c) == 0x08)) {
++ /* select upper threshold */
++ if (mask & 0x10) { /* upper crit */
++ sd->lim1 = 1;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x1000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x20) { /* upper non-recov */
++ sd->lim1 = 0;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x2000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x08) { /* upper non-crit */
++ sd->lim1 = 2;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0800))
++ sd->lim1_write = 1;
++ }
++
++ /* select lower threshold */
++ if ((((capab & 0x30) == 0x10) || /* readable ? */
++ ((capab & 0x30) == 0x20)) && /* pos hyst */
++ sd->stype == STYPE_TEMP)
++ sd->lim2 = 6;
++ else if (mask & 0x02) { /* lower crit */
++ sd->lim2 = 4;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0200))
++ sd->lim2_write = 1;
++ } else if (mask & 0x04) { /* lower non-recov */
++ sd->lim2 = 3;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0400))
++ sd->lim2_write = 1;
++ } else if (mask & 0x01) { /* lower non-crit */
++ sd->lim2 = 5;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0100))
++ sd->lim2_write = 1;
++ }
++ }
++
++ /* swap lim1/lim2 if m < 0 or function is 1/x (but not both!) */
++ if ((sd->m < 0 && sd->linear != 7) || (sd->m >= 0 && sd->linear == 7)) {
++ tmp = sd->lim1;
++ sd->lim1 = sd->lim2;
++ sd->lim2 = tmp;
++ }
++
++ if (sd->lim1 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for upper limit\n",
++ threshold_text[sd->lim1]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable upper limit\n");
++
++ if (sd->lim2 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for lower limit\n",
++ threshold_text[sd->lim2]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable lower limit\n");
++}
++
++/************* sysfs callback functions *********/
++static ssize_t show_update_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ return snprintf(buf, 20, "%d\n", aattr->bmc->update_period);
++}
++
++static ssize_t store_update_period(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ aattr->bmc->update_period = simple_strtoul(buf, NULL, 10);;
++ return count;
++};
++
++static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ return snprintf(buf, 20, "%ld\n",
++ conv_val(sattr->sdr->reading, sattr->sdr));
++}
++
++static ssize_t show_sensor_max(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long max = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim1 >= 0)
++ max = conv_val(sattr->sdr->limits[sattr->sdr->lim1],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", max);
++}
++
++static ssize_t show_sensor_min(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long min = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim2 >= 0)
++ min = conv_val(sattr->sdr->limits[sattr->sdr->lim2],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", min);
++};
++
++static ssize_t show_sensor_label(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ u8 label[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ ipmisensors_sprintf(label, sattr->sdr->id, sattr->sdr->string_type,
++ sattr->sdr->id_length);
++ return snprintf(buf, 20, "%s\n", label);
++};
++
++static ssize_t store_sensor_max(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set max on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim1);
++ return count;
++};
++
++static ssize_t store_sensor_min(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set min on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim2);
++ return count;
++};
++
++static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++ return snprintf(buf, 20, "%d\n", aattr->bmc->alarms);
++};
++
++static ssize_t show_name(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return snprintf(buf, 20, "%s\n", driver_data.driver_name);
++};
++
++/* work function to build the sysfs entries using the ipmi sdrs */
++static void ipmisensors_build_sysfs(struct work_struct *work)
++{
++ int temps = 0, volts = 0, currs = 0, fans = 0;
++ struct sdrdata *cursor, *next;
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, sysfs_work);
++
++ /* find and create entries for each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++
++ cursor->attr_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_max_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_min_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ return;
++ }
++ }
++
++ if (cursor->attr_name == NULL || cursor->attr_max_name == NULL
++ || cursor->attr_min_name == NULL
++ || cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "temp%d_input", ++temps);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "temp%d_max", temps);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "temp%d_min", temps);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "temp%d_label", temps);
++ break;
++ case (STYPE_VOLT):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "in%d_input", ++volts);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "in%d_max", volts);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "in%d_min", volts);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "in%d_label", volts);
++ break;
++ case (STYPE_CURR):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "curr%d_input", ++currs);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "curr%d_max", currs);
++ sprintf(cursor->attr_min_name, "curr%d_min", currs);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "curr%d_label", currs);
++ break;
++ case (STYPE_FAN):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "fan%d_input", ++fans);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "fan%d_max", fans);
++ sprintf(cursor->attr_min_name, "fan%d_min", fans);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "fan%d_label", fans);
++ break;
++ default:
++ printk(KERN_INFO "ipmisensors: unkown sensor type\n");
++ continue;
++ }
++
++ cursor->attr.dev_attr.attr.name = cursor->attr_name;
++ cursor->attr.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr.dev_attr.show = show_sensor;
++ cursor->attr.dev_attr.store = NULL;
++ cursor->attr.sdr = cursor;
++
++ cursor->attr_min.dev_attr.attr.name = cursor->attr_min_name;
++ cursor->attr_min.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_min.dev_attr.show = show_sensor_min;
++ cursor->attr_min.sdr = cursor;
++
++ if (cursor->lim2_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_min.dev_attr.store = store_sensor_min;
++ cursor->attr_min.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_min.dev_attr.store = NULL;
++ cursor->attr_min.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ cursor->attr_max.dev_attr.attr.name = cursor->attr_max_name;
++ cursor->attr_max.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_max.dev_attr.show = show_sensor_max;
++ cursor->attr_max.sdr = cursor;
++
++ if (cursor->lim1_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_max.dev_attr.store = store_sensor_max;
++ cursor->attr_max.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_max.dev_attr.store = NULL;
++ cursor->attr_max.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label.dev_attr.attr.name =
++ cursor->attr_label_name;
++ cursor->attr_label.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr_label.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_label.dev_attr.show = show_sensor_label;
++ cursor->attr_label.dev_attr.store = NULL;
++ cursor->attr_label.sdr = cursor;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registering sensor %d: (type 0x%.2x) "
++ "(fmt=%d; m=%d; b=%d; k1=%d; k2=%d; cap=0x%.2x; mask=0x%.4x)\n",
++ cursor->number, cursor->stype, cursor->format, cursor->m,
++ cursor->b, cursor->k & 0xf, cursor->k >> 4,
++ cursor->capab, cursor->thresh_mask);
++
++ if (cursor->id_length > 0) {
++ ipmisensors_sprintf(id, cursor->id, cursor->string_type,
++ cursor->id_length);
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label temp%d \"%s\"\n",
++ temps, id);
++ break;
++ case (STYPE_VOLT):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label in%d \"%s\"\n",
++ volts, id);
++ break;
++ case (STYPE_CURR):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label curr%d \"%s\"\n",
++ currs, id);
++ break;
++ case (STYPE_FAN):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label fan%d \"%s\"\n",
++ fans, id);
++ break;
++ }
++ }
++
++ ipmisensors_select_thresholds(cursor);
++
++ if (cursor->linear != 0 && cursor->linear != 7) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: nonlinear function 0x%.2x unsupported, expect bad results\n",
++ cursor->number, cursor->linear);
++ }
++
++ if ((cursor->format & 0x03) == 0x02) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: 1's complement format unsupported, expect bad results\n",
++ cursor->number);
++ } else if ((cursor->format & 0x03) == 0x03) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: threshold sensor only, no readings available",
++ cursor->number);
++ }
++
++ if (cursor->lim1_write || cursor->lim2_write)
++ cursor->attr.dev_attr.attr.mode = 0644;
++ else
++ cursor->attr.dev_attr.attr.mode = 0444;
++
++ if (device_create_file(bmc->dev, &cursor->attr.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_min.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_max.dev_attr) < 0
++ || (cursor->id_length >
++ 0 ? device_create_file(bmc->dev,
++ &cursor->attr_label.dev_attr) <
++ 0 : 0)
++ ) {
++ printk(KERN_INFO
++ "ipmisensors: sysfs file creation failed for SDR %d (%s).\n",
++ cursor->number, cursor->id);
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++ }
++
++ bmc->alarms_attr.dev_attr.attr.name = "alarms";
++ bmc->alarms_attr.dev_attr.attr.mode = S_IRUGO;
++ bmc->alarms_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->alarms_attr.dev_attr.show = show_alarms;
++ bmc->alarms_attr.dev_attr.store = NULL;
++ bmc->alarms_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->alarms_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'alarms'");
++ return;
++ }
++
++ bmc->name_attr.attr.name = "name";
++ bmc->name_attr.attr.mode = S_IRUGO;
++ bmc->name_attr.attr.owner = THIS_MODULE;
++ bmc->name_attr.show = show_name;
++
++ if (device_create_file(bmc->dev, &bmc->name_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'name'");
++ return;
++ }
++
++ bmc->update_attr.dev_attr.attr.name = "update_period";
++ bmc->update_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ bmc->update_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->update_attr.dev_attr.show = show_update_period;
++ bmc->update_attr.dev_attr.store = store_update_period;
++ bmc->update_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->update_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'update_period'");
++ return;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registered %d temp, %d volt, %d current, %d fan sensors\n",
++ temps, volts, currs, fans);
++
++ /* This completes the initialization. We can now kickoff the
++ * periodic update of the bmc sensor's values by scheduling
++ * the first work.
++ */
++ queue_work(ipmisensors_workqueue, &bmc->update_work.work);
++
++}
++
++/**
++ * Process an SDR response message, save the SDRs we like in the sdr
++ * list for the given BMC.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_sdr_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ u16 record;
++ int type;
++ int stype;
++ int id_length;
++ int i;
++ int ipmi_ver = 0;
++ unsigned char *data;
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct sdrdata *sdr;
++
++ if (msg->data[0] != 0) {
++ /* cut request in half and try again */
++ bmc->ipmi_sdr_partial_size /= 2;
++ if (bmc->ipmi_sdr_partial_size < 8) {
++ printk(KERN_INFO
++ "ipmisensors: IPMI buffers too small, giving up\n");
++ bmc->state = STATE_DONE;
++ return;
++ }
++ printk(KERN_DEBUG
++ "ipmisensors: Reducing SDR request size to %d\n",
++ bmc->ipmi_sdr_partial_size);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ if (bmc->ipmi_sdr_partial_size < IPMI_SDR_SIZE) {
++ if (bmc->rx_msg_data_offset == 0) {
++ memcpy(bmc->rx_msg_data, msg->data,
++ bmc->ipmi_sdr_partial_size + 3);
++ bmc->rx_msg_data_offset =
++ bmc->ipmi_sdr_partial_size + 3;
++ } else {
++ memcpy(bmc->rx_msg_data + bmc->rx_msg_data_offset,
++ msg->data + 3, bmc->ipmi_sdr_partial_size);
++ bmc->rx_msg_data_offset += bmc->ipmi_sdr_partial_size;
++ }
++ if (bmc->rx_msg_data_offset > bmc->rx_msg_data[7] + 7) {
++ /* got last chunk */
++ bmc->rx_msg_data_offset = 0;
++ data = bmc->rx_msg_data;
++ } else {
++ /* get more */
++ record =
++ (bmc->rx_msg_data[4] << 8) | bmc->rx_msg_data[3];
++ ipmisensors_get_sdr(bmc, bmc->resid, record,
++ bmc->rx_msg_data_offset - 3);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ } else {
++ /* got it in one chunk */
++ data = msg->data;
++ }
++
++ bmc->nextrecord = (data[2] << 8) | data[1];
++
++ /* If the ipmi version is 0.9 we have to remap some things.
++ * Yes this is very ugly, but we aren't the ones who
++ * implemented an incomplete spec!
++ */
++ ipmi_ver = data[5];
++
++ type = data[6];
++ /* known SDR type */
++ if (type == 1 || type == 2) {
++ stype = data[(ipmi_ver == 0x90 ? 16 : 15)];
++ /* known sensor type */
++ if (stype <= STYPE_MAX) {
++ if (data[(ipmi_ver == 0x90 ? 17 : 16)] != 0x01) {
++ if (type == 1)
++ ipmisensors_sprintf(id, &data[51],
++ data[50] >> 6,
++ data[50] & 0x1f);
++ else
++ ipmisensors_sprintf(id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 :
++ 35)],
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] >> 6,
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] & 0x1f);
++ printk(KERN_INFO
++ "ipmisensors: skipping non-threshold sensor \"%s\"\n",
++ id);
++ } else {
++ /* add entry to sdrd table */
++ sdr = ipmisensors_new_sdr();
++ if (!sdr) {
++ printk(KERN_ERR
++ "ipmisensors: could not allocate memory for new SDR");
++ return;
++ }
++ sdr->bmc = bmc;
++ sdr->stype = stype;
++ sdr->number = data[10];
++ sdr->capab = data[(ipmi_ver == 0x90 ? 15 : 14)];
++ sdr->thresh_mask =
++ (((u16) data[(ipmi_ver == 0x90 ? 21 : 22)])
++ << 8) | data[21];
++ if (type == 1) {
++ sdr->format =
++ data[(ipmi_ver ==
++ 0x90 ? 22 : 24)] >> 6;
++ sdr->linear =
++ data[(ipmi_ver ==
++ 0x90 ? 25 : 26)] & 0x7f;
++ sdr->m =
++ data[(ipmi_ver == 0x90 ? 26 : 27)];
++ sdr->m |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 27 : 28)]
++ & 0xc0)) << 2;
++ if (sdr->m & 0x0200) {
++ /* sign extend */
++ sdr->m |= 0xfc00;
++ }
++ sdr->b =
++ data[(ipmi_ver == 0x90 ? 28 : 29)];
++ sdr->b |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 29 : 30)]
++ & 0xc0)) << 2;
++ if (sdr->b & 0x0200) {
++ /* sign extend */
++ sdr->b |= 0xfc00;
++ }
++ sdr->k =
++ data[(ipmi_ver == 0x90 ? 31 : 32)];
++ sdr->nominal =
++ data[(ipmi_ver == 0x90 ? 33 : 34)];
++ for (i = 0; i < SDR_LIMITS; i++) {
++ /* assume readable */
++ sdr->limits[i] =
++ data[(ipmi_ver ==
++ 0x90 ? 40 : 39) + i];
++ }
++ sdr->string_type = data[50] >> 6;
++ id_length = data[50] & 0x1f;
++ memcpy(sdr->id, &data[51], id_length);
++ sdr->id_length = id_length;
++ } else {
++ sdr->m = 1;
++ sdr->b = 0;
++ sdr->k = 0;
++ sdr->string_type =
++ data[(ipmi_ver ==
++ 0x90 ? 29 : 34)] >> 6;
++ id_length = data[34] & 0x1f;
++ if (id_length > 0) {
++ memcpy(sdr->id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 : 35)],
++ id_length);
++ }
++ sdr->id_length = id_length;
++ /* limits?? */
++ if (ipmi_ver == 0x90) {
++ memcpy(sdr->id,
++ &data[30], id_length);
++ sdr->id_length = id_length;
++ }
++ }
++ ipmisensors_add_sdr(bmc, sdr);
++ }
++ }
++ /* peek at the other SDR types */
++ } else if (type == 0x10 || type == 0x11 || type == 0x12) {
++ ipmisensors_sprintf(id, data + 19, data[18] >> 6,
++ data[18] & 0x1f);
++ if (type == 0x10) {
++ printk(KERN_INFO
++ "ipmisensors: Generic Device acc=0x%x; slv=0x%x; lun=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[13], id);
++ } else if (type == 0x11) {
++ printk(KERN_INFO
++ "ipmisensors: FRU Device acc=0x%x; slv=0x%x; log=0x%x; ch=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[11], data[13],
++ id);
++ } else {
++ printk(KERN_INFO
++ "ipmisensors: Mgmt Ctllr Device slv=0x%x; \"%s\"\n",
++ data[8], id);
++ }
++ } else if (type == 0x14) {
++ printk(KERN_INFO
++ "ipmisensors: Message Channel Info Records:\n");
++ for (i = 0; i < 8; i++) {
++ printk(KERN_INFO "ipmisensors: Channel %d info 0x%x\n",
++ i, data[9 + i]);
++ }
++ } else {
++ printk(KERN_INFO "ipmisensors: Skipping SDR type 0x%x\n", type);
++ }
++ if (ipmi_ver != 0x90) {
++ if (bmc->nextrecord >= 6224) {
++ /*YJ stop sensor scan on poweredge 1750 */
++ bmc->nextrecord = 0xffff;
++ }
++ }
++
++ if (bmc->nextrecord == 0xFFFF) {
++ if (bmc->sdr_count == 0) {
++ printk(KERN_INFO
++ "ipmisensors: No recognized sensors found.\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_INFO "ipmisensors: all sensors detected\n");
++ bmc->state = STATE_SYSTABLE;
++
++ /* Schedule sysfs build/registration work */
++ INIT_WORK(&bmc->sysfs_work, ipmisensors_build_sysfs);
++ queue_work(ipmisensors_workqueue, &bmc->sysfs_work);
++ }
++ } else {
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ }
++}
++
++/**
++ * Process incoming messages based on internal state
++ *
++ * @bmc: the bmc the message is from.
++ * @msg: the ipmi message to process.
++ */
++static void ipmisensors_rcv_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ switch (bmc->state) {
++ case STATE_INIT:
++ case STATE_RESERVE:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got first resid 0x%.4x\n",
++ bmc->resid);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_SDR:
++ case STATE_SDRPARTIAL:
++ ipmisensors_rcv_sdr_msg(bmc, msg);
++ break;
++
++ case STATE_READING:
++ ipmisensors_rcv_reading_msg(bmc, msg);
++ break;
++
++ case STATE_UNCANCEL:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got new resid 0x%.4x\n",
++ bmc->resid);
++
++ bmc->rx_msg_data_offset = 0;
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_DONE:
++ case STATE_SYSTABLE:
++ break;
++ default:
++ bmc->state = STATE_INIT;
++ }
++}
++
++/**
++ * Callback to handle a received IPMI message from a given BMC.
++ *
++ * @msg: the received message.
++ * @handler_data: a pointer to the particular bmc ipmisensors_bmc_data struct.
++ */
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data)
++{
++ struct ipmisensors_bmc_data *bmc =
++ (struct ipmisensors_bmc_data *)user_msg_data;
++
++ if (msg->msg.data[0] != 0)
++ printk(KERN_WARNING
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x\n",
++ msg->msg.data[0], msg->msg.netfn, msg->msg.cmd);
++
++ if (bmc != NULL && ipmisensors_intf_registered(bmc->interface_id)) {
++ if (bmc->state == STATE_SDR &&
++ msg->msg.data[0] == IPMI_INVALID_RESERVATION_ID) {
++ /* reservation cancelled, get new resid */
++ if (++bmc->errorcount > 275) {
++ printk(KERN_ERR
++ "ipmisensors: Too many reservations cancelled, giving up\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_DEBUG
++ "ipmisensors: resid 0x%04x cancelled, getting new one\n",
++ bmc->resid);
++
++ ipmisensors_reserve_sdr(bmc);
++ bmc->state = STATE_UNCANCEL;
++ }
++ } else if (msg->msg.data[0] != IPMI_CC_NO_ERROR &&
++ msg->msg.data[0] != IPMI_ERR_RETURNING_REQ_BYTES &&
++ msg->msg.data[0] != IPMI_ERR_PROVIDING_RESPONSE) {
++ printk(KERN_ERR
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x; state = %d; probably fatal.\n",
++ msg->msg.data[0], msg->msg.netfn & 0xfe,
++ msg->msg.cmd, bmc->state);
++ } else {
++ printk(KERN_DEBUG "ipmisensors: received message\n");
++ ipmisensors_rcv_msg(bmc, &msg->msg);
++ }
++
++ } else {
++ printk(KERN_WARNING
++ "ipmisensors: Response for non-registered BMC\n");
++ if (bmc != NULL)
++ printk(KERN_DEBUG "ipmisensors: BMC ID: %d\n",
++ bmc->interface_id);
++ else
++ printk(KERN_DEBUG "ipmisensors: BMC NULL!\n");
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++/****** IPMI Interface Initialization ******/
++
++/**
++ * Return true if the given ipmi interface has been registered.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static int ipmisensors_intf_registered(int ipmi_intf)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Return true if the given BMC has been registered.
++ *
++ * @bmc: The BMC device.
++ */
++static int ipmisensors_bmc_registered(struct device *bmc)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->dev == bmc) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Register new IPMI BMC interface. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address)
++{
++ int error;
++
++ /* allocate a new ipmisensors_bmc_data struct */
++
++ struct ipmisensors_bmc_data *bmc = (struct ipmisensors_bmc_data *)
++ kmalloc(sizeof(struct ipmisensors_bmc_data), GFP_KERNEL);
++
++ /* initialize members */
++ INIT_LIST_HEAD(&bmc->sdrs);
++ bmc->interface_id = ipmi_intf;
++
++ bmc->address = *address;
++
++ bmc->sdr_count = 0;
++ bmc->msgid = 0;
++ bmc->ipmi_sdr_partial_size = IPMI_CHUNK_SIZE;
++ bmc->state = STATE_INIT;
++ bmc->errorcount = 0;
++ bmc->rx_msg_data_offset = 0;
++ bmc->dev = ipmi_get_bmcdevice(ipmi_intf);
++
++ /* default to 3 second min update interval */
++ bmc->update_period = 3;
++
++ if (bmc->dev == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error, couldn't get BMC device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Create IPMI messaging interface user */
++ error = ipmi_create_user(bmc->interface_id, &driver_data.ipmi_hndlrs,
++ bmc, &bmc->user);
++ if (error < 0) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register user with ipmi interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC as a HWMON class device */
++ bmc->class_dev = hwmon_device_register(bmc->dev);
++
++ if (IS_ERR(bmc->class_dev)) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register hwmon class device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC in the driver */
++ if (ipmisensors_bmc_registered(bmc->dev)) {
++ printk(KERN_ERR
++ "ipmisensors: BMC on interface %d already registered\n",
++ bmc->interface_id);
++ hwmon_device_unregister(bmc->class_dev);
++ kfree(bmc);
++ return;
++ }
++
++ ipmi_get_version(bmc->user, &bmc->ipmi_version_major,
++ &bmc->ipmi_version_minor);
++
++ /* finally add the new bmc data to the bmc data list */
++ list_add_tail(&bmc->list, &driver_data.bmc_data);
++ driver_data.interfaces++;
++
++ printk(KERN_INFO
++ "ipmisensors: Registered IPMI %d.%d BMC over interface %d\n",
++ bmc->ipmi_version_major,
++ bmc->ipmi_version_minor, bmc->interface_id);
++
++ /* Send a reserve SDR command to the bmc */
++ ipmisensors_reserve_sdr(bmc);
++
++ /* initialize the bmc's update work struct */
++ INIT_DELAYED_WORK(&bmc->update_work, ipmisensors_update_bmc);
++}
++
++/**
++ * Callback for when an IPMI BMC is gone. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_unregister_bmc(int ipmi_intf)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ list_del(&cursor->list);
++ printk(KERN_DEBUG
++ "ipmisensors: cancelling queued work\n");
++ /* cancel update work queued for this bmc */
++ cancel_delayed_work(&cursor->update_work);
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev,
++ &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev,
++ &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ driver_data.interfaces--;
++ }
++ }
++
++}
++
++/**
++ * Unregister all registered bmcs.
++ */
++static void ipmisensors_unregister_bmc_all(void)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ list_del(&cursor->list);
++
++ /* cancel update work queued for this bmc */
++ printk(KERN_DEBUG "ipmisensors: cancelling queued work\n");
++ cancel_delayed_work(&cursor->update_work);
++
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev, &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev, &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ }
++
++ driver_data.interfaces = 0;
++}
++
++/**
++ * Callback for when a new IPMI SMI type interface is found.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_new_smi(int if_num, struct device *dev)
++{
++ struct ipmi_addr smi_address = {
++ IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
++ IPMI_BMC_CHANNEL,
++ {0},
++ };
++
++ /* calls the generic new interface function */
++ ipmisensors_register_bmc(if_num, &smi_address);
++}
++
++/**
++ * Callback for when an exisiting IPMI SMI type interface is gone.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_smi_gone(int if_num)
++{
++ if (driver_data.interfaces > 0) {
++ ipmisensors_unregister_bmc(if_num);
++ }
++}
++
++/**
++ * Initialize the module.
++ */
++static int __init ipmisensors_init(void)
++{
++ int error;
++ printk(KERN_INFO "ipmisensors - IPMI BMC sensors interface\n");
++
++ /* init cache managers */
++ driver_data.sdrdata_cache =
++ kmem_cache_create("ipmisensors_sdrdata", sizeof(struct sdrdata), 0,
++ 0, NULL, NULL);
++ driver_data.sysfsattr_cache =
++ kmem_cache_create("ipmisensors_sysfsattr",
++ sizeof(struct ipmisensors_device_attribute), 0, 0,
++ NULL, NULL);
++
++ if (!driver_data.sdrdata_cache || !driver_data.sysfsattr_cache) {
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++ return -ENOMEM;
++ }
++
++ /* register IPMI interface callback(s) */
++ error = ipmi_smi_watcher_register(&driver_data.smi_watcher);
++ if (error) {
++ printk(KERN_WARNING
++ "ipmisensors: can't register smi watcher\n");
++ return error;
++ }
++
++ /* create work queue, keep it simple, single-threaded */
++ ipmisensors_workqueue =
++ create_singlethread_workqueue("ipmisensors_workqueue");
++
++ return 0;
++}
++
++/**
++ * Cleanup
++ */
++static void ipmisensors_cleanup(void)
++{
++ /* start cleanup */
++ cleanup = 1;
++
++ /* unregister bmcs */
++ printk(KERN_DEBUG "ipmisensors: unregister bmcs\n");
++ ipmi_smi_watcher_unregister(&driver_data.smi_watcher);
++ ipmisensors_unregister_bmc_all();
++
++ /* flush & destroy work queue */
++ printk(KERN_DEBUG "ipmisensors: destroy workqueue\n");
++ flush_workqueue(ipmisensors_workqueue);
++ destroy_workqueue(ipmisensors_workqueue);
++
++ /* remove cache managers */
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++}
++
++/**
++ * Cleanup and exit the module
++ */
++static void __exit ipmisensors_exit(void)
++{
++ ipmisensors_cleanup();
++ printk(KERN_DEBUG "ipmisensors: cleanup finished\n");
++}
++
++MODULE_AUTHOR("Yani Ioannou <yani.ioannou@gmail.com>");
++MODULE_DESCRIPTION("IPMI BMC sensors");
++MODULE_LICENSE("GPL");
++
++module_init(ipmisensors_init);
++module_exit(ipmisensors_exit);
+diff -rduNp linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.h linux-2.6.20.3/drivers/hwmon/ipmisensors.h
+--- linux-2.6.20.3.orig/drivers/hwmon/ipmisensors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.20.3/drivers/hwmon/ipmisensors.h 2007-03-14 14:41:23.000000000 +0100
+@@ -0,0 +1,240 @@
++/*
++ * ipmisensors.h - lm_sensors interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/ipmi.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++
++/* SDR defs */
++#define STYPE_TEMP 0x01
++#define STYPE_VOLT 0x02
++#define STYPE_CURR 0x03
++#define STYPE_FAN 0x04
++
++#define SDR_LIMITS 8
++#define SDR_MAX_ID_LENGTH 16
++#define SDR_MAX_UNPACKED_ID_LENGTH ((SDR_MAX_ID_LENGTH * 4 / 3) + 2)
++
++/* the last sensor type we are interested in */
++#define STYPE_MAX 4
++
++#define IPMI_SDR_SIZE 67
++#define IPMI_CHUNK_SIZE 16
++
++#define MAX_FILENAME_LENGTH 30
++
++struct ipmisensors_device_attribute {
++ struct device_attribute dev_attr;
++ struct sdrdata *sdr;
++};
++#define to_ipmisensors_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_device_attribute, dev_attr)
++
++#define IPMISENSORS_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
++struct ipmisensors_attribute sensor_dev_attr_##_name = { \
++ .dev_attr = __ATTR(_name,_mode,_show,_store), \
++ .index = _index, \
++}
++
++struct ipmisensors_bmc_device_attribute {
++ struct device_attribute dev_attr;
++ struct ipmisensors_bmc_data *bmc;
++};
++#define to_ipmisensors_bmc_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_bmc_device_attribute, dev_attr)
++
++/**
++ * &struct_sdrdata stores the IPMI Sensor Data Record (SDR) data, as recieved from the BMC, along with the corresponding sysfs attributes
++ */
++struct sdrdata {
++ struct list_head list;
++ /* retrieved from SDR, not expected to change */
++ /* Sensor Type Code */
++ u8 stype;
++ u8 number;
++ /* Sensor Capability Code */
++ u8 capab;
++ u16 thresh_mask;
++ u8 format;
++ u8 linear;
++ s16 m;
++ s16 b;
++ u8 k;
++ u8 nominal;
++ u8 limits[SDR_LIMITS];
++ /* index into limits for reported upper and lower limit */
++ int lim1, lim2;
++ u8 lim1_write, lim2_write;
++ u8 string_type;
++ u8 id_length;
++ u8 id[SDR_MAX_ID_LENGTH];
++ /* retrieved from reading */
++ u8 reading;
++ u8 status;
++ u8 thresholds;
++ /* sensor's bmc */
++ struct ipmisensors_bmc_data *bmc;
++ /* sysfs entries */
++ struct ipmisensors_device_attribute attr;
++ char *attr_name;
++ struct ipmisensors_device_attribute attr_min;
++ char *attr_min_name;
++ struct ipmisensors_device_attribute attr_max;
++ char *attr_max_name;
++ struct ipmisensors_device_attribute attr_label;
++ char *attr_label_name;
++
++};
++
++/**
++ * &struct_ipmisensors_data stores the data for the ipmisensors driver.
++ */
++struct ipmisensors_data {
++ /* Driver struct */
++ char *driver_name;
++
++ /* Linked list of ipmisensors_bmc_data structs, one for each BMC */
++ struct list_head bmc_data;
++
++ /* Number of ipmi interfaces (and hence ipmisensors_data structs). */
++ int interfaces;
++
++ /* IPMI kernel interface - SMI watcher */
++ struct ipmi_smi_watcher smi_watcher;
++
++ /* IPMI kernel interface - user handlers */
++ struct ipmi_user_hndl ipmi_hndlrs;
++
++ /* Cache manager for sdrdata cache */
++ struct kmem_cache *sdrdata_cache;
++
++ /* Cache manager for ipmi_sensor_device_attribute cache */
++ struct kmem_cache *sysfsattr_cache;
++};
++
++/**
++ * &states: enumeration of state codes for a bmc specific ipmisensors
++ */
++enum states {
++ STATE_INIT,
++ STATE_RESERVE,
++ STATE_SDR,
++ STATE_SDRPARTIAL,
++ STATE_READING,
++ STATE_UNCANCEL,
++ STATE_SYSTABLE,
++ STATE_DONE
++};
++
++/**
++ * &struct_ipmisensors_bmc_data stores the data for a particular IPMI BMC.
++ */
++struct ipmisensors_bmc_data {
++ struct list_head list;
++
++ /* The IPMI interface number */
++ int interface_id;
++
++ /* The IPMI address */
++ struct ipmi_addr address;
++
++ /* List of sdrdata structs (sdrs) recieved from the BMC */
++ struct list_head sdrs;
++
++ /* Count of the number of sdrs stored in the sdr list */
++ int sdr_count;
++
++ /* next message id */
++ int msgid;
++
++ /* The ipmi interface 'user' used to access this particular bmc */
++ ipmi_user_t user;
++
++ /* BMC IPMI Version (major) */
++ unsigned char ipmi_version_major;
++
++ /* BMC IPMI Version (minor) */
++ unsigned char ipmi_version_minor;
++
++ /* The size of the SDR request message */
++ int ipmi_sdr_partial_size;
++
++ /* transmit message buffer */
++ struct kernel_ipmi_msg tx_message;
++
++ /* ipmi transmited data buffer */
++ unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; /* why the +50 in bmcsensors? */
++
++ /* ipmi recieved data buffer */
++ unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH + 50];
++
++ /* current recieve buffer offset */
++ int rx_msg_data_offset;
++
++ /* The id of then next SDR record to read during update cycle */
++ u16 nextrecord;
++
++ /* BMC SDR Reservation ID */
++ u16 resid;
++
++ /* Alarm status */
++ u8 alarms;
++
++ /* The cumalative error count for this bmc */
++ int errorcount;
++
++ /* The current state of this bmc w.r.t. ipmisensors (see enum states) */
++ int state;
++
++ /* The current sdr for which a reading is pending */
++ struct sdrdata *current_sdr;
++
++ /* The BMC's device struct */
++ struct device *dev;
++
++ /* hwmon class device */
++ struct class_device *class_dev;
++
++ /* hwmon device name */
++ struct device_attribute name_attr;
++
++ /* alarms attribute */
++ struct ipmisensors_bmc_device_attribute alarms_attr;
++
++ /* update_period attribute */
++ struct ipmisensors_bmc_device_attribute update_attr;
++
++ /* lower bound on time between updates (in seconds) */
++ unsigned int update_period;
++
++ /* semaphore used to do a headcount of the SDR readings we are waiting
++ * on in a given bmc update */
++ struct semaphore update_semaphore;
++
++ /* bmc's work struct for updating sensors */
++ struct delayed_work update_work;
++
++ /* bmc's work struct for building the sysfs workqueue */
++ struct work_struct sysfs_work;
++};
+diff -rduNp linux-2.6.20.3.orig/include/linux/ipmi.h linux-2.6.20.3/include/linux/ipmi.h
+--- linux-2.6.20.3.orig/include/linux/ipmi.h 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/include/linux/ipmi.h 2007-03-14 14:23:02.000000000 +0100
+@@ -300,6 +300,9 @@ int ipmi_create_user(unsigned int
+ safe, too. */
+ int ipmi_destroy_user(ipmi_user_t user);
+
++/* Get the IPMI BMC's device struct */
++struct device *ipmi_get_bmcdevice(int ipmi_intf);
++
+ /* Get the IPMI version of the BMC we are talking to. */
+ void ipmi_get_version(ipmi_user_t user,
+ unsigned char *major,
+diff -rduNp linux-2.6.20.3.orig/include/linux/ipmi_msgdefs.h linux-2.6.20.3/include/linux/ipmi_msgdefs.h
+--- linux-2.6.20.3.orig/include/linux/ipmi_msgdefs.h 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.3/include/linux/ipmi_msgdefs.h 2007-03-14 14:23:02.000000000 +0100
+@@ -45,6 +45,7 @@
+
+ #define IPMI_NETFN_APP_REQUEST 0x06
+ #define IPMI_NETFN_APP_RESPONSE 0x07
++#define IPMI_GET_DEVICE_GUID_CMD 0x08
+ #define IPMI_GET_DEVICE_ID_CMD 0x01
+ #define IPMI_COLD_RESET_CMD 0x02
+ #define IPMI_WARM_RESET_CMD 0x03
+@@ -57,6 +58,11 @@
+ #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
+ #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
+ #define IPMI_GET_CHANNEL_INFO_CMD 0x42
++#define IPMI_RESERVE_SDR 0x22
++#define IPMI_GET_SDR 0x23
++#define IPMI_GET_SENSOR_STATE_READING 0x2D
++#define IPMI_SET_SENSOR_HYSTERESIS 0x24
++#define IPMI_SET_SENSOR_THRESHOLD 0x26
+
+ #define IPMI_NETFN_STORAGE_REQUEST 0x0a
+ #define IPMI_NETFN_STORAGE_RESPONSE 0x0b
+@@ -79,10 +85,13 @@
+ #define IPMI_NODE_BUSY_ERR 0xc0
+ #define IPMI_INVALID_COMMAND_ERR 0xc1
+ #define IPMI_TIMEOUT_ERR 0xc3
++#define IPMI_INVALID_RESERVATION_ID 0xc5
+ #define IPMI_ERR_MSG_TRUNCATED 0xc6
+ #define IPMI_REQ_LEN_INVALID_ERR 0xc7
+ #define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
+ #define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
++#define IPMI_ERR_RETURNING_REQ_BYTES 0xca
++#define IPMI_ERR_PROVIDING_RESPONSE 0xce
+ #define IPMI_LOST_ARBITRATION_ERR 0x81
+ #define IPMI_BUS_ERR 0x82
+ #define IPMI_NAK_ON_WRITE_ERR 0x83
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.1-007-ipmisensors-20070314-1214.patch b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.1-007-ipmisensors-20070314-1214.patch
new file mode 100644
index 0000000000..5fe74954f3
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.1-007-ipmisensors-20070314-1214.patch
@@ -0,0 +1,1914 @@
+diff -rduNp linux-2.6.22.1.oorig2/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.22.1/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.22.1.oorig2/drivers/char/ipmi/ipmi_msghandler.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/char/ipmi/ipmi_msghandler.c 2007-07-24 14:22:26.000000000 +0200
+@@ -1953,6 +1953,24 @@ static void remove_proc_entries(ipmi_smi
+ #endif /* CONFIG_PROC_FS */
+ }
+
++/*
++ * Retrieves the bmc_device struct for a given ipmi interface number (or NULL if none).
++ */
++struct device *ipmi_get_bmcdevice(int if_num)
++{
++ ipmi_smi_t intf;
++ mutex_lock(&ipmi_interfaces_mutex);
++ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
++ if (intf->intf_num == if_num){
++ mutex_unlock(&ipmi_interfaces_mutex);
++ return &intf->bmc->dev->dev;
++ }
++ }
++ mutex_unlock(&ipmi_interfaces_mutex);
++
++ return NULL;
++}
++
+ static int __find_bmc_guid(struct device *dev, void *data)
+ {
+ unsigned char *id = data;
+@@ -4196,3 +4214,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN);
+ EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+ EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+ EXPORT_SYMBOL(ipmi_free_recv_msg);
++EXPORT_SYMBOL(ipmi_get_bmcdevice);
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/Kconfig linux-2.6.22.1/drivers/hwmon/Kconfig
+--- linux-2.6.22.1.oorig2/drivers/hwmon/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/hwmon/Kconfig 2007-07-24 14:22:26.000000000 +0200
+@@ -248,6 +248,16 @@ config SENSORS_CORETEMP
+ sensor inside your CPU. Supported all are all known variants
+ of Intel Core family.
+
++config SENSORS_IPMI
++ tristate "IPMI Hardware Monitoring Support"
++ depends on HWMON && IPMI_HANDLER && EXPERIMENTAL
++ help
++ If you say yes here you get support for sensors monitored by
++ an IPMI baseboard management controller (BMC).
++
++ This driver can also be built as a module. If so, the module
++ will be called ipmisensors.
++
+ config SENSORS_IT87
+ tristate "ITE IT87xx and compatibles"
+ depends on I2C
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/Makefile linux-2.6.22.1/drivers/hwmon/Makefile
+--- linux-2.6.22.1.oorig2/drivers/hwmon/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/hwmon/Makefile 2007-07-24 14:22:26.000000000 +0200
+@@ -32,6 +32,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
+ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
++obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o
+ obj-$(CONFIG_SENSORS_IT87) += it87.o
+ obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
+ obj-$(CONFIG_SENSORS_LM63) += lm63.o
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.c linux-2.6.22.1/drivers/hwmon/ipmisensors.c
+--- linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/drivers/hwmon/ipmisensors.c 2007-07-24 14:22:26.000000000 +0200
+@@ -0,0 +1,1552 @@
++/*
++ * ipmisensors.c - lm-sensors/hwmon interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/init.h>
++#include <linux/module.h>
++#include <linux/param.h>
++#include <linux/hwmon.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/device.h>
++#include <linux/hwmon.h>
++
++#include "ipmisensors.h"
++
++/****** Function Prototypes ******/
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg);
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc);
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset);
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index);
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr);
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data);
++static int ipmisensors_intf_registered(int ipmi_intf);
++static int ipmisensors_bmc_registered(struct device *bmc);
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address);
++static void ipmisensors_unregister_bmc(int ipmi_intf);
++static void ipmisensors_unregister_bmc_all(void);
++static void ipmisensors_new_smi(int if_num, struct device *dev);
++static void ipmisensors_smi_gone(int if_num);
++static void ipmisensors_update_bmc(struct work_struct *);
++static void ipmisensors_cleanup(void);
++
++/****** Static Vars ******/
++
++/* set when module is being removed */
++static int cleanup = 0;
++
++/* ipmisensors driver data */
++static struct ipmisensors_data driver_data = {
++ .driver_name = "bmc",
++ .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data),
++ .interfaces = 0,
++ .smi_watcher = {
++ .owner = THIS_MODULE,
++ .new_smi = ipmisensors_new_smi,
++ .smi_gone = ipmisensors_smi_gone,
++ },
++ .ipmi_hndlrs = {
++ .ipmi_recv_hndl = ipmisensors_msg_handler,
++ },
++};
++
++/* sensor refresh workqueue */
++static struct workqueue_struct *ipmisensors_workqueue;
++
++/****** SDR List Functions ******/
++/**
++ * Creates a new sdrdata struct, or returns NULL if insufficient memory.
++ */
++static struct sdrdata *ipmisensors_new_sdr(void)
++{
++ struct sdrdata *sdr;
++
++ sdr = kmem_cache_alloc(driver_data.sdrdata_cache, GFP_ATOMIC);
++ if (sdr) {
++ memset(sdr, 0, sizeof(struct sdrdata));
++ } else {
++ printk(KERN_ERR
++ "ipmisensors: Couldn't allocate memory for new SDR\n");
++ }
++
++ return sdr;
++}
++
++/**
++ * Adds the given sdrdata struct to the given bmc's SDR list.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static inline void ipmisensors_add_sdr(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ list_add(&sdr->list, &bmc->sdrs);
++ printk(KERN_DEBUG
++ "ipmisensors: SDR %d: type 0x%02x (%s)\n",
++ bmc->sdr_count, sdr->stype, sdr->id);
++ bmc->sdr_count++;
++}
++
++/**
++ * Cleanup the sdr list for the given BMC.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_sdr_cleanup(struct ipmisensors_bmc_data *bmc)
++{
++ struct sdrdata *cursor, *next;
++
++ /* find and free each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ device_remove_file(bmc->dev, &cursor->attr.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_min.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_max.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_label.dev_attr);
++
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++
++ list_del(&cursor->list);
++ kmem_cache_free(driver_data.sdrdata_cache, cursor);
++ }
++}
++
++/* worker function for workqueue ipmisensors_workqueue */
++static void ipmisensors_update_bmc(struct work_struct *work)
++{
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, update_work.work);
++
++ /* don't start an update cycle if one already in progress */
++ if (bmc->state != STATE_READING) {
++ struct sdrdata *cursor, *next;
++ bmc->state = STATE_READING;
++ printk(KERN_DEBUG "ipmisensors: starting update\n");
++
++ /* init semaphore to 1 for update cycle */
++ sema_init(&bmc->update_semaphore, 1);
++
++ /* update each sdr reading */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ ipmisensors_get_reading(bmc, cursor);
++ }
++ }
++
++ /* wait for readings (need timeout?) */
++ down_interruptible(&bmc->update_semaphore);
++
++ printk(KERN_DEBUG "ipmisensors: update complete\n");
++
++ bmc->state = STATE_DONE;
++
++ /* if the module isn't cleaning up, schedule another update */
++ if (!cleanup)
++ queue_delayed_work(ipmisensors_workqueue, &bmc->update_work,
++ bmc->update_period * HZ);
++}
++
++/****** IPMI Message Sending ******/
++
++/**
++ * Send a message to the IPMI BMC
++ *
++ * @bmc: the bmc to send the message to.
++ * @msgid: the message id to use.
++ * @msg: the ipmi message structure.
++ */
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg)
++{
++ if (msg->data == NULL)
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x\n", msg->cmd);
++ else
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x 0x%x 0x%x\n",
++ msg->cmd, msg->data[0], msg->data[1]);
++
++ /* This should be ipmi_request, but Corey had to remove
++ * that due to it being unused at the moment, as soon as
++ * this makes it into the kernel we should request it be re-instated.
++ */
++ ipmi_request_settime(bmc->user, &bmc->address, msgid, msg, bmc, 0,
++ -1, 0);
++}
++
++/**
++ * Compose and send a "reserve SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_RESERVE_SDR;
++ bmc->tx_message.data_len = 0;
++ bmc->tx_message.data = NULL;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Componse and send a "get SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @res_id:
++ * @record:
++ * @offset:
++ */
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset)
++{
++ printk(KERN_DEBUG "ipmisensors: Get SDR 0x%x 0x%x 0x%x\n",
++ res_id, record, offset);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SDR;
++ bmc->tx_message.data_len = 6;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = res_id & 0xff;
++ bmc->tx_msg_data[1] = res_id >> 8;
++ bmc->tx_msg_data[2] = record & 0xff;
++ bmc->tx_msg_data[3] = record >> 8;
++ bmc->tx_msg_data[4] = offset;
++ bmc->tx_msg_data[5] = bmc->ipmi_sdr_partial_size;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "set sensor threshold" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @id: the ipmi id number of the sensor.
++ * @value: the new value for the threshold.
++ * @lim_index: the index in the lim[] array for which this value applies.
++ */
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index)
++{
++ int i;
++
++ printk(KERN_DEBUG "ipmisensors: Set SDR Threshold %d %d %d\n",
++ number, value, lim_index);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_SET_SENSOR_THRESHOLD;
++ bmc->tx_message.data_len = 8;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = number & 0xff;
++ bmc->tx_msg_data[1] = 0x01 << lim_index;
++
++ if (lim_index > 5 || lim_index < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Error - ipmisensors_set_sensor_threshold given invalid lim_index\n");
++ return;
++ }
++
++ for (i = 2; i < 8; i++)
++ bmc->tx_msg_data[i] = 0x00;
++
++ bmc->tx_msg_data[lim_index] = value && 0xff;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "get sensor reading" message for the given sdr.
++ *
++ * @bmc: the bmc to send the message to.
++ * @sdr: the sdr of the sensor to get the reading for.
++ */
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SENSOR_STATE_READING;
++ bmc->tx_message.data_len = 1;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = sdr->number;
++ bmc->current_sdr = sdr;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++ down_interruptible(&bmc->update_semaphore);
++}
++
++/****** IPMI Message Receiving ******/
++
++/**
++ * Process an sensor reading response message.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_reading_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ struct sdrdata *sdr = bmc->current_sdr;
++
++ if (sdr == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error ipmisensors_rcv_reading with NULL sdr\n");
++ return;
++ }
++
++ sdr->reading = msg->data[1];
++ sdr->status = msg->data[2];
++ sdr->thresholds = msg->data[3];
++
++ printk(KERN_DEBUG "ipmisensors: sensor %d (type %d) reading %d\n",
++ sdr->number, sdr->stype, msg->data[1]);
++
++ up(&bmc->update_semaphore);
++}
++
++/**
++ * Unpack based on string type, convert to normal, null terminate.
++ */
++static void ipmisensors_sprintf(u8 * to, u8 * from, u8 type, u8 length)
++{
++ static const u8 *bcdplus = "0123456789 -.:,_";
++ int i;
++
++ switch (type) {
++ case 0: /* unicode */
++ for (i = 0; i < length; i++)
++ *to++ = (*from++ & 0x7f);
++ *to = 0;
++ break;
++ case 1: /* BCD Plus */
++ for (i = 0; i < length; i++)
++ *to++ = bcdplus[*from++ & 0x0f];
++ *to = 0;
++ break;
++ case 2: /* packed ascii *//* if not a mult. of 3 this will run over */
++ for (i = 0; i < length; i += 3) {
++ *to++ = *from & 0x3f;
++ *to++ = *from >> 6 | ((*(from+1) & 0xf) << 2);
++ from++;
++ *to++ = *from >> 4 | ((*(from+1) & 0x3) << 4);
++ from++;
++ *to++ = (*from++ >> 2) & 0x3f;
++ }
++ *to = 0;
++ break;
++ case 3: /* normal */
++ if (length > 1)
++ memcpy(to, from, length);
++ to[length] = 0;
++ break;
++ }
++}
++
++/* IPMI V1.5 Section 30 */
++static const int exps[] =
++ { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
++
++/* Return 0 for fan, 2 for temp, 3 for voltage
++ We could make it variable based on the accuracy (= log10(m * 10**k2));
++ this would work for /proc output, however libsensors resolution
++ is statically set in lib/chips.c */
++static int decplaces(struct sdrdata *sd)
++{
++ switch (sd->stype) {
++ case STYPE_TEMP:
++ return 2;
++ case STYPE_CURR:
++ case STYPE_VOLT:
++ return 3;
++ case STYPE_FAN:
++ default:
++ return 0;
++ }
++}
++
++/* convert a raw value to a reading. IMPI V1.5 Section 30 */
++static long conv_val(int value, struct sdrdata *sd)
++{
++ u8 k1, k2;
++ long r;
++
++ r = value * sd->m;
++ k1 = sd->k & 0x0f;
++ k2 = sd->k >> 4;
++ if (k1 < 8)
++ r += sd->b * exps[k1];
++ else
++ r += sd->b / exps[16 - k1];
++ r *= exps[decplaces(sd)];
++ if (k2 < 8) {
++ if (sd->linear != 7)
++ r *= exps[k2];
++ else
++ /* this will always truncate to 0: r = 1 / (exps[k2] * r); */
++ r = 0;
++ } else {
++ if (sd->linear != 7)
++ r /= exps[16 - k2];
++ else {
++ if (r != 0)
++ /* 1 / x * 10 ** (-m) == 10 ** m / x */
++ r = exps[16 - k2] / r;
++ else
++ r = 0;
++ }
++ }
++
++ return r;
++}
++
++static const char *threshold_text[] = {
++ "upper non-recoverable threshold",
++ "upper critical threshold",
++ "upper non-critical threshold",
++ "lower non-recoverable threshold",
++ "lower critical threshold",
++ "lower non-critical threshold",
++ "positive-going hysteresis",
++ "negative-going hysteresis" /* unused */
++};
++
++/* select two out of the 8 possible readable thresholds, and place indexes into the limits
++ array into lim1 and lim2. Set writable flags */
++static void ipmisensors_select_thresholds(struct sdrdata *sd)
++{
++ u8 capab = sd->capab;
++ u16 mask = sd->thresh_mask;
++ int tmp;
++
++ sd->lim1 = -1;
++ sd->lim2 = -1;
++ sd->lim1_write = 0;
++ sd->lim2_write = 0;
++
++ if (((capab & 0x0c) == 0x04) || /* readable thresholds ? */
++ ((capab & 0x0c) == 0x08)) {
++ /* select upper threshold */
++ if (mask & 0x10) { /* upper crit */
++ sd->lim1 = 1;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x1000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x20) { /* upper non-recov */
++ sd->lim1 = 0;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x2000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x08) { /* upper non-crit */
++ sd->lim1 = 2;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0800))
++ sd->lim1_write = 1;
++ }
++
++ /* select lower threshold */
++ if ((((capab & 0x30) == 0x10) || /* readable ? */
++ ((capab & 0x30) == 0x20)) && /* pos hyst */
++ sd->stype == STYPE_TEMP)
++ sd->lim2 = 6;
++ else if (mask & 0x02) { /* lower crit */
++ sd->lim2 = 4;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0200))
++ sd->lim2_write = 1;
++ } else if (mask & 0x04) { /* lower non-recov */
++ sd->lim2 = 3;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0400))
++ sd->lim2_write = 1;
++ } else if (mask & 0x01) { /* lower non-crit */
++ sd->lim2 = 5;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0100))
++ sd->lim2_write = 1;
++ }
++ }
++
++ /* swap lim1/lim2 if m < 0 or function is 1/x (but not both!) */
++ if ((sd->m < 0 && sd->linear != 7) || (sd->m >= 0 && sd->linear == 7)) {
++ tmp = sd->lim1;
++ sd->lim1 = sd->lim2;
++ sd->lim2 = tmp;
++ }
++
++ if (sd->lim1 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for upper limit\n",
++ threshold_text[sd->lim1]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable upper limit\n");
++
++ if (sd->lim2 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for lower limit\n",
++ threshold_text[sd->lim2]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable lower limit\n");
++}
++
++/************* sysfs callback functions *********/
++static ssize_t show_update_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ return snprintf(buf, 20, "%d\n", aattr->bmc->update_period);
++}
++
++static ssize_t store_update_period(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ aattr->bmc->update_period = simple_strtoul(buf, NULL, 10);;
++ return count;
++};
++
++static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ return snprintf(buf, 20, "%ld\n",
++ conv_val(sattr->sdr->reading, sattr->sdr));
++}
++
++static ssize_t show_sensor_max(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long max = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim1 >= 0)
++ max = conv_val(sattr->sdr->limits[sattr->sdr->lim1],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", max);
++}
++
++static ssize_t show_sensor_min(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long min = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim2 >= 0)
++ min = conv_val(sattr->sdr->limits[sattr->sdr->lim2],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", min);
++};
++
++static ssize_t show_sensor_label(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ u8 label[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ ipmisensors_sprintf(label, sattr->sdr->id, sattr->sdr->string_type,
++ sattr->sdr->id_length);
++ return snprintf(buf, 20, "%s\n", label);
++};
++
++static ssize_t store_sensor_max(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set max on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim1);
++ return count;
++};
++
++static ssize_t store_sensor_min(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set min on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim2);
++ return count;
++};
++
++static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++ return snprintf(buf, 20, "%d\n", aattr->bmc->alarms);
++};
++
++static ssize_t show_name(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return snprintf(buf, 20, "%s\n", driver_data.driver_name);
++};
++
++/* work function to build the sysfs entries using the ipmi sdrs */
++static void ipmisensors_build_sysfs(struct work_struct *work)
++{
++ int temps = 0, volts = 0, currs = 0, fans = 0;
++ struct sdrdata *cursor, *next;
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, sysfs_work);
++
++ /* find and create entries for each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++
++ cursor->attr_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_max_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_min_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ return;
++ }
++ }
++
++ if (cursor->attr_name == NULL || cursor->attr_max_name == NULL
++ || cursor->attr_min_name == NULL
++ || cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "temp%d_input", ++temps);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "temp%d_max", temps);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "temp%d_min", temps);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "temp%d_label", temps);
++ break;
++ case (STYPE_VOLT):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "in%d_input", ++volts);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "in%d_max", volts);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "in%d_min", volts);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "in%d_label", volts);
++ break;
++ case (STYPE_CURR):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "curr%d_input", ++currs);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "curr%d_max", currs);
++ sprintf(cursor->attr_min_name, "curr%d_min", currs);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "curr%d_label", currs);
++ break;
++ case (STYPE_FAN):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "fan%d_input", ++fans);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "fan%d_max", fans);
++ sprintf(cursor->attr_min_name, "fan%d_min", fans);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "fan%d_label", fans);
++ break;
++ default:
++ printk(KERN_INFO "ipmisensors: unkown sensor type\n");
++ continue;
++ }
++
++ cursor->attr.dev_attr.attr.name = cursor->attr_name;
++ cursor->attr.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr.dev_attr.show = show_sensor;
++ cursor->attr.dev_attr.store = NULL;
++ cursor->attr.sdr = cursor;
++
++ cursor->attr_min.dev_attr.attr.name = cursor->attr_min_name;
++ cursor->attr_min.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_min.dev_attr.show = show_sensor_min;
++ cursor->attr_min.sdr = cursor;
++
++ if (cursor->lim2_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_min.dev_attr.store = store_sensor_min;
++ cursor->attr_min.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_min.dev_attr.store = NULL;
++ cursor->attr_min.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ cursor->attr_max.dev_attr.attr.name = cursor->attr_max_name;
++ cursor->attr_max.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_max.dev_attr.show = show_sensor_max;
++ cursor->attr_max.sdr = cursor;
++
++ if (cursor->lim1_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_max.dev_attr.store = store_sensor_max;
++ cursor->attr_max.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_max.dev_attr.store = NULL;
++ cursor->attr_max.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label.dev_attr.attr.name =
++ cursor->attr_label_name;
++ cursor->attr_label.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr_label.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_label.dev_attr.show = show_sensor_label;
++ cursor->attr_label.dev_attr.store = NULL;
++ cursor->attr_label.sdr = cursor;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registering sensor %d: (type 0x%.2x) "
++ "(fmt=%d; m=%d; b=%d; k1=%d; k2=%d; cap=0x%.2x; mask=0x%.4x)\n",
++ cursor->number, cursor->stype, cursor->format, cursor->m,
++ cursor->b, cursor->k & 0xf, cursor->k >> 4,
++ cursor->capab, cursor->thresh_mask);
++
++ if (cursor->id_length > 0) {
++ ipmisensors_sprintf(id, cursor->id, cursor->string_type,
++ cursor->id_length);
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label temp%d \"%s\"\n",
++ temps, id);
++ break;
++ case (STYPE_VOLT):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label in%d \"%s\"\n",
++ volts, id);
++ break;
++ case (STYPE_CURR):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label curr%d \"%s\"\n",
++ currs, id);
++ break;
++ case (STYPE_FAN):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label fan%d \"%s\"\n",
++ fans, id);
++ break;
++ }
++ }
++
++ ipmisensors_select_thresholds(cursor);
++
++ if (cursor->linear != 0 && cursor->linear != 7) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: nonlinear function 0x%.2x unsupported, expect bad results\n",
++ cursor->number, cursor->linear);
++ }
++
++ if ((cursor->format & 0x03) == 0x02) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: 1's complement format unsupported, expect bad results\n",
++ cursor->number);
++ } else if ((cursor->format & 0x03) == 0x03) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: threshold sensor only, no readings available",
++ cursor->number);
++ }
++
++ if (cursor->lim1_write || cursor->lim2_write)
++ cursor->attr.dev_attr.attr.mode = 0644;
++ else
++ cursor->attr.dev_attr.attr.mode = 0444;
++
++ if (device_create_file(bmc->dev, &cursor->attr.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_min.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_max.dev_attr) < 0
++ || (cursor->id_length >
++ 0 ? device_create_file(bmc->dev,
++ &cursor->attr_label.dev_attr) <
++ 0 : 0)
++ ) {
++ printk(KERN_INFO
++ "ipmisensors: sysfs file creation failed for SDR %d (%s).\n",
++ cursor->number, cursor->id);
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++ }
++
++ bmc->alarms_attr.dev_attr.attr.name = "alarms";
++ bmc->alarms_attr.dev_attr.attr.mode = S_IRUGO;
++ bmc->alarms_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->alarms_attr.dev_attr.show = show_alarms;
++ bmc->alarms_attr.dev_attr.store = NULL;
++ bmc->alarms_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->alarms_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'alarms'");
++ return;
++ }
++
++ bmc->name_attr.attr.name = "name";
++ bmc->name_attr.attr.mode = S_IRUGO;
++ bmc->name_attr.attr.owner = THIS_MODULE;
++ bmc->name_attr.show = show_name;
++
++ if (device_create_file(bmc->dev, &bmc->name_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'name'");
++ return;
++ }
++
++ bmc->update_attr.dev_attr.attr.name = "update_period";
++ bmc->update_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ bmc->update_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->update_attr.dev_attr.show = show_update_period;
++ bmc->update_attr.dev_attr.store = store_update_period;
++ bmc->update_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->update_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'update_period'");
++ return;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registered %d temp, %d volt, %d current, %d fan sensors\n",
++ temps, volts, currs, fans);
++
++ /* This completes the initialization. We can now kickoff the
++ * periodic update of the bmc sensor's values by scheduling
++ * the first work.
++ */
++ queue_work(ipmisensors_workqueue, &bmc->update_work.work);
++
++}
++
++/**
++ * Process an SDR response message, save the SDRs we like in the sdr
++ * list for the given BMC.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_sdr_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ u16 record;
++ int type;
++ int stype;
++ int id_length;
++ int i;
++ int ipmi_ver = 0;
++ unsigned char *data;
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct sdrdata *sdr;
++
++ if (msg->data[0] != 0) {
++ /* cut request in half and try again */
++ bmc->ipmi_sdr_partial_size /= 2;
++ if (bmc->ipmi_sdr_partial_size < 8) {
++ printk(KERN_INFO
++ "ipmisensors: IPMI buffers too small, giving up\n");
++ bmc->state = STATE_DONE;
++ return;
++ }
++ printk(KERN_DEBUG
++ "ipmisensors: Reducing SDR request size to %d\n",
++ bmc->ipmi_sdr_partial_size);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ if (bmc->ipmi_sdr_partial_size < IPMI_SDR_SIZE) {
++ if (bmc->rx_msg_data_offset == 0) {
++ memcpy(bmc->rx_msg_data, msg->data,
++ bmc->ipmi_sdr_partial_size + 3);
++ bmc->rx_msg_data_offset =
++ bmc->ipmi_sdr_partial_size + 3;
++ } else {
++ memcpy(bmc->rx_msg_data + bmc->rx_msg_data_offset,
++ msg->data + 3, bmc->ipmi_sdr_partial_size);
++ bmc->rx_msg_data_offset += bmc->ipmi_sdr_partial_size;
++ }
++ if (bmc->rx_msg_data_offset > bmc->rx_msg_data[7] + 7) {
++ /* got last chunk */
++ bmc->rx_msg_data_offset = 0;
++ data = bmc->rx_msg_data;
++ } else {
++ /* get more */
++ record =
++ (bmc->rx_msg_data[4] << 8) | bmc->rx_msg_data[3];
++ ipmisensors_get_sdr(bmc, bmc->resid, record,
++ bmc->rx_msg_data_offset - 3);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ } else {
++ /* got it in one chunk */
++ data = msg->data;
++ }
++
++ bmc->nextrecord = (data[2] << 8) | data[1];
++
++ /* If the ipmi version is 0.9 we have to remap some things.
++ * Yes this is very ugly, but we aren't the ones who
++ * implemented an incomplete spec!
++ */
++ ipmi_ver = data[5];
++
++ type = data[6];
++ /* known SDR type */
++ if (type == 1 || type == 2) {
++ stype = data[(ipmi_ver == 0x90 ? 16 : 15)];
++ /* known sensor type */
++ if (stype <= STYPE_MAX) {
++ if (data[(ipmi_ver == 0x90 ? 17 : 16)] != 0x01) {
++ if (type == 1)
++ ipmisensors_sprintf(id, &data[51],
++ data[50] >> 6,
++ data[50] & 0x1f);
++ else
++ ipmisensors_sprintf(id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 :
++ 35)],
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] >> 6,
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] & 0x1f);
++ printk(KERN_INFO
++ "ipmisensors: skipping non-threshold sensor \"%s\"\n",
++ id);
++ } else {
++ /* add entry to sdrd table */
++ sdr = ipmisensors_new_sdr();
++ if (!sdr) {
++ printk(KERN_ERR
++ "ipmisensors: could not allocate memory for new SDR");
++ return;
++ }
++ sdr->bmc = bmc;
++ sdr->stype = stype;
++ sdr->number = data[10];
++ sdr->capab = data[(ipmi_ver == 0x90 ? 15 : 14)];
++ sdr->thresh_mask =
++ (((u16) data[(ipmi_ver == 0x90 ? 21 : 22)])
++ << 8) | data[21];
++ if (type == 1) {
++ sdr->format =
++ data[(ipmi_ver ==
++ 0x90 ? 22 : 24)] >> 6;
++ sdr->linear =
++ data[(ipmi_ver ==
++ 0x90 ? 25 : 26)] & 0x7f;
++ sdr->m =
++ data[(ipmi_ver == 0x90 ? 26 : 27)];
++ sdr->m |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 27 : 28)]
++ & 0xc0)) << 2;
++ if (sdr->m & 0x0200) {
++ /* sign extend */
++ sdr->m |= 0xfc00;
++ }
++ sdr->b =
++ data[(ipmi_ver == 0x90 ? 28 : 29)];
++ sdr->b |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 29 : 30)]
++ & 0xc0)) << 2;
++ if (sdr->b & 0x0200) {
++ /* sign extend */
++ sdr->b |= 0xfc00;
++ }
++ sdr->k =
++ data[(ipmi_ver == 0x90 ? 31 : 32)];
++ sdr->nominal =
++ data[(ipmi_ver == 0x90 ? 33 : 34)];
++ for (i = 0; i < SDR_LIMITS; i++) {
++ /* assume readable */
++ sdr->limits[i] =
++ data[(ipmi_ver ==
++ 0x90 ? 40 : 39) + i];
++ }
++ sdr->string_type = data[50] >> 6;
++ id_length = data[50] & 0x1f;
++ memcpy(sdr->id, &data[51], id_length);
++ sdr->id_length = id_length;
++ } else {
++ sdr->m = 1;
++ sdr->b = 0;
++ sdr->k = 0;
++ sdr->string_type =
++ data[(ipmi_ver ==
++ 0x90 ? 29 : 34)] >> 6;
++ id_length = data[34] & 0x1f;
++ if (id_length > 0) {
++ memcpy(sdr->id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 : 35)],
++ id_length);
++ }
++ sdr->id_length = id_length;
++ /* limits?? */
++ if (ipmi_ver == 0x90) {
++ memcpy(sdr->id,
++ &data[30], id_length);
++ sdr->id_length = id_length;
++ }
++ }
++ ipmisensors_add_sdr(bmc, sdr);
++ }
++ }
++ /* peek at the other SDR types */
++ } else if (type == 0x10 || type == 0x11 || type == 0x12) {
++ ipmisensors_sprintf(id, data + 19, data[18] >> 6,
++ data[18] & 0x1f);
++ if (type == 0x10) {
++ printk(KERN_INFO
++ "ipmisensors: Generic Device acc=0x%x; slv=0x%x; lun=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[13], id);
++ } else if (type == 0x11) {
++ printk(KERN_INFO
++ "ipmisensors: FRU Device acc=0x%x; slv=0x%x; log=0x%x; ch=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[11], data[13],
++ id);
++ } else {
++ printk(KERN_INFO
++ "ipmisensors: Mgmt Ctllr Device slv=0x%x; \"%s\"\n",
++ data[8], id);
++ }
++ } else if (type == 0x14) {
++ printk(KERN_INFO
++ "ipmisensors: Message Channel Info Records:\n");
++ for (i = 0; i < 8; i++) {
++ printk(KERN_INFO "ipmisensors: Channel %d info 0x%x\n",
++ i, data[9 + i]);
++ }
++ } else {
++ printk(KERN_INFO "ipmisensors: Skipping SDR type 0x%x\n", type);
++ }
++ if (ipmi_ver != 0x90) {
++ if (bmc->nextrecord >= 6224) {
++ /*YJ stop sensor scan on poweredge 1750 */
++ bmc->nextrecord = 0xffff;
++ }
++ }
++
++ if (bmc->nextrecord == 0xFFFF) {
++ if (bmc->sdr_count == 0) {
++ printk(KERN_INFO
++ "ipmisensors: No recognized sensors found.\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_INFO "ipmisensors: all sensors detected\n");
++ bmc->state = STATE_SYSTABLE;
++
++ /* Schedule sysfs build/registration work */
++ INIT_WORK(&bmc->sysfs_work, ipmisensors_build_sysfs);
++ queue_work(ipmisensors_workqueue, &bmc->sysfs_work);
++ }
++ } else {
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ }
++}
++
++/**
++ * Process incoming messages based on internal state
++ *
++ * @bmc: the bmc the message is from.
++ * @msg: the ipmi message to process.
++ */
++static void ipmisensors_rcv_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ switch (bmc->state) {
++ case STATE_INIT:
++ case STATE_RESERVE:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got first resid 0x%.4x\n",
++ bmc->resid);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_SDR:
++ case STATE_SDRPARTIAL:
++ ipmisensors_rcv_sdr_msg(bmc, msg);
++ break;
++
++ case STATE_READING:
++ ipmisensors_rcv_reading_msg(bmc, msg);
++ break;
++
++ case STATE_UNCANCEL:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got new resid 0x%.4x\n",
++ bmc->resid);
++
++ bmc->rx_msg_data_offset = 0;
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_DONE:
++ case STATE_SYSTABLE:
++ break;
++ default:
++ bmc->state = STATE_INIT;
++ }
++}
++
++/**
++ * Callback to handle a received IPMI message from a given BMC.
++ *
++ * @msg: the received message.
++ * @handler_data: a pointer to the particular bmc ipmisensors_bmc_data struct.
++ */
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data)
++{
++ struct ipmisensors_bmc_data *bmc =
++ (struct ipmisensors_bmc_data *)user_msg_data;
++
++ if (msg->msg.data[0] != 0)
++ printk(KERN_WARNING
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x\n",
++ msg->msg.data[0], msg->msg.netfn, msg->msg.cmd);
++
++ if (bmc != NULL && ipmisensors_intf_registered(bmc->interface_id)) {
++ if (bmc->state == STATE_SDR &&
++ msg->msg.data[0] == IPMI_INVALID_RESERVATION_ID) {
++ /* reservation cancelled, get new resid */
++ if (++bmc->errorcount > 275) {
++ printk(KERN_ERR
++ "ipmisensors: Too many reservations cancelled, giving up\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_DEBUG
++ "ipmisensors: resid 0x%04x cancelled, getting new one\n",
++ bmc->resid);
++
++ ipmisensors_reserve_sdr(bmc);
++ bmc->state = STATE_UNCANCEL;
++ }
++ } else if (msg->msg.data[0] != IPMI_CC_NO_ERROR &&
++ msg->msg.data[0] != IPMI_ERR_RETURNING_REQ_BYTES &&
++ msg->msg.data[0] != IPMI_ERR_PROVIDING_RESPONSE) {
++ printk(KERN_ERR
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x; state = %d; probably fatal.\n",
++ msg->msg.data[0], msg->msg.netfn & 0xfe,
++ msg->msg.cmd, bmc->state);
++ } else {
++ printk(KERN_DEBUG "ipmisensors: received message\n");
++ ipmisensors_rcv_msg(bmc, &msg->msg);
++ }
++
++ } else {
++ printk(KERN_WARNING
++ "ipmisensors: Response for non-registered BMC\n");
++ if (bmc != NULL)
++ printk(KERN_DEBUG "ipmisensors: BMC ID: %d\n",
++ bmc->interface_id);
++ else
++ printk(KERN_DEBUG "ipmisensors: BMC NULL!\n");
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++/****** IPMI Interface Initialization ******/
++
++/**
++ * Return true if the given ipmi interface has been registered.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static int ipmisensors_intf_registered(int ipmi_intf)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Return true if the given BMC has been registered.
++ *
++ * @bmc: The BMC device.
++ */
++static int ipmisensors_bmc_registered(struct device *bmc)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->dev == bmc) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Register new IPMI BMC interface. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address)
++{
++ int error;
++
++ /* allocate a new ipmisensors_bmc_data struct */
++
++ struct ipmisensors_bmc_data *bmc = (struct ipmisensors_bmc_data *)
++ kmalloc(sizeof(struct ipmisensors_bmc_data), GFP_KERNEL);
++
++ /* initialize members */
++ INIT_LIST_HEAD(&bmc->sdrs);
++ bmc->interface_id = ipmi_intf;
++
++ bmc->address = *address;
++
++ bmc->sdr_count = 0;
++ bmc->msgid = 0;
++ bmc->ipmi_sdr_partial_size = IPMI_CHUNK_SIZE;
++ bmc->state = STATE_INIT;
++ bmc->errorcount = 0;
++ bmc->rx_msg_data_offset = 0;
++ bmc->dev = ipmi_get_bmcdevice(ipmi_intf);
++
++ /* default to 3 second min update interval */
++ bmc->update_period = 3;
++
++ if (bmc->dev == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error, couldn't get BMC device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Create IPMI messaging interface user */
++ error = ipmi_create_user(bmc->interface_id, &driver_data.ipmi_hndlrs,
++ bmc, &bmc->user);
++ if (error < 0) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register user with ipmi interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC as a HWMON class device */
++ bmc->class_dev = hwmon_device_register(bmc->dev);
++
++ if (IS_ERR(bmc->class_dev)) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register hwmon class device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC in the driver */
++ if (ipmisensors_bmc_registered(bmc->dev)) {
++ printk(KERN_ERR
++ "ipmisensors: BMC on interface %d already registered\n",
++ bmc->interface_id);
++ hwmon_device_unregister(bmc->class_dev);
++ kfree(bmc);
++ return;
++ }
++
++ ipmi_get_version(bmc->user, &bmc->ipmi_version_major,
++ &bmc->ipmi_version_minor);
++
++ /* finally add the new bmc data to the bmc data list */
++ list_add_tail(&bmc->list, &driver_data.bmc_data);
++ driver_data.interfaces++;
++
++ printk(KERN_INFO
++ "ipmisensors: Registered IPMI %d.%d BMC over interface %d\n",
++ bmc->ipmi_version_major,
++ bmc->ipmi_version_minor, bmc->interface_id);
++
++ /* Send a reserve SDR command to the bmc */
++ ipmisensors_reserve_sdr(bmc);
++
++ /* initialize the bmc's update work struct */
++ INIT_DELAYED_WORK(&bmc->update_work, ipmisensors_update_bmc);
++}
++
++/**
++ * Callback for when an IPMI BMC is gone. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_unregister_bmc(int ipmi_intf)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ list_del(&cursor->list);
++ printk(KERN_DEBUG
++ "ipmisensors: cancelling queued work\n");
++ /* cancel update work queued for this bmc */
++ cancel_delayed_work(&cursor->update_work);
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev,
++ &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev,
++ &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ driver_data.interfaces--;
++ }
++ }
++
++}
++
++/**
++ * Unregister all registered bmcs.
++ */
++static void ipmisensors_unregister_bmc_all(void)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ list_del(&cursor->list);
++
++ /* cancel update work queued for this bmc */
++ printk(KERN_DEBUG "ipmisensors: cancelling queued work\n");
++ cancel_delayed_work(&cursor->update_work);
++
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev, &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev, &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ }
++
++ driver_data.interfaces = 0;
++}
++
++/**
++ * Callback for when a new IPMI SMI type interface is found.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_new_smi(int if_num, struct device *dev)
++{
++ struct ipmi_addr smi_address = {
++ IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
++ IPMI_BMC_CHANNEL,
++ {0},
++ };
++
++ /* calls the generic new interface function */
++ ipmisensors_register_bmc(if_num, &smi_address);
++}
++
++/**
++ * Callback for when an exisiting IPMI SMI type interface is gone.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_smi_gone(int if_num)
++{
++ if (driver_data.interfaces > 0) {
++ ipmisensors_unregister_bmc(if_num);
++ }
++}
++
++/**
++ * Initialize the module.
++ */
++static int __init ipmisensors_init(void)
++{
++ int error;
++ printk(KERN_INFO "ipmisensors - IPMI BMC sensors interface\n");
++
++ /* init cache managers */
++ driver_data.sdrdata_cache =
++ kmem_cache_create("ipmisensors_sdrdata", sizeof(struct sdrdata), 0,
++ 0, NULL, NULL);
++ driver_data.sysfsattr_cache =
++ kmem_cache_create("ipmisensors_sysfsattr",
++ sizeof(struct ipmisensors_device_attribute), 0, 0,
++ NULL, NULL);
++
++ if (!driver_data.sdrdata_cache || !driver_data.sysfsattr_cache) {
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++ return -ENOMEM;
++ }
++
++ /* register IPMI interface callback(s) */
++ error = ipmi_smi_watcher_register(&driver_data.smi_watcher);
++ if (error) {
++ printk(KERN_WARNING
++ "ipmisensors: can't register smi watcher\n");
++ return error;
++ }
++
++ /* create work queue, keep it simple, single-threaded */
++ ipmisensors_workqueue =
++ create_singlethread_workqueue("ipmisensors_workqueue");
++
++ return 0;
++}
++
++/**
++ * Cleanup
++ */
++static void ipmisensors_cleanup(void)
++{
++ /* start cleanup */
++ cleanup = 1;
++
++ /* unregister bmcs */
++ printk(KERN_DEBUG "ipmisensors: unregister bmcs\n");
++ ipmi_smi_watcher_unregister(&driver_data.smi_watcher);
++ ipmisensors_unregister_bmc_all();
++
++ /* flush & destroy work queue */
++ printk(KERN_DEBUG "ipmisensors: destroy workqueue\n");
++ flush_workqueue(ipmisensors_workqueue);
++ destroy_workqueue(ipmisensors_workqueue);
++
++ /* remove cache managers */
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++}
++
++/**
++ * Cleanup and exit the module
++ */
++static void __exit ipmisensors_exit(void)
++{
++ ipmisensors_cleanup();
++ printk(KERN_DEBUG "ipmisensors: cleanup finished\n");
++}
++
++MODULE_AUTHOR("Yani Ioannou <yani.ioannou@gmail.com>");
++MODULE_DESCRIPTION("IPMI BMC sensors");
++MODULE_LICENSE("GPL");
++
++module_init(ipmisensors_init);
++module_exit(ipmisensors_exit);
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.h linux-2.6.22.1/drivers/hwmon/ipmisensors.h
+--- linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/drivers/hwmon/ipmisensors.h 2007-07-24 14:22:26.000000000 +0200
+@@ -0,0 +1,240 @@
++/*
++ * ipmisensors.h - lm_sensors interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/ipmi.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++
++/* SDR defs */
++#define STYPE_TEMP 0x01
++#define STYPE_VOLT 0x02
++#define STYPE_CURR 0x03
++#define STYPE_FAN 0x04
++
++#define SDR_LIMITS 8
++#define SDR_MAX_ID_LENGTH 16
++#define SDR_MAX_UNPACKED_ID_LENGTH ((SDR_MAX_ID_LENGTH * 4 / 3) + 2)
++
++/* the last sensor type we are interested in */
++#define STYPE_MAX 4
++
++#define IPMI_SDR_SIZE 67
++#define IPMI_CHUNK_SIZE 16
++
++#define MAX_FILENAME_LENGTH 30
++
++struct ipmisensors_device_attribute {
++ struct device_attribute dev_attr;
++ struct sdrdata *sdr;
++};
++#define to_ipmisensors_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_device_attribute, dev_attr)
++
++#define IPMISENSORS_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
++struct ipmisensors_attribute sensor_dev_attr_##_name = { \
++ .dev_attr = __ATTR(_name,_mode,_show,_store), \
++ .index = _index, \
++}
++
++struct ipmisensors_bmc_device_attribute {
++ struct device_attribute dev_attr;
++ struct ipmisensors_bmc_data *bmc;
++};
++#define to_ipmisensors_bmc_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_bmc_device_attribute, dev_attr)
++
++/**
++ * &struct_sdrdata stores the IPMI Sensor Data Record (SDR) data, as recieved from the BMC, along with the corresponding sysfs attributes
++ */
++struct sdrdata {
++ struct list_head list;
++ /* retrieved from SDR, not expected to change */
++ /* Sensor Type Code */
++ u8 stype;
++ u8 number;
++ /* Sensor Capability Code */
++ u8 capab;
++ u16 thresh_mask;
++ u8 format;
++ u8 linear;
++ s16 m;
++ s16 b;
++ u8 k;
++ u8 nominal;
++ u8 limits[SDR_LIMITS];
++ /* index into limits for reported upper and lower limit */
++ int lim1, lim2;
++ u8 lim1_write, lim2_write;
++ u8 string_type;
++ u8 id_length;
++ u8 id[SDR_MAX_ID_LENGTH];
++ /* retrieved from reading */
++ u8 reading;
++ u8 status;
++ u8 thresholds;
++ /* sensor's bmc */
++ struct ipmisensors_bmc_data *bmc;
++ /* sysfs entries */
++ struct ipmisensors_device_attribute attr;
++ char *attr_name;
++ struct ipmisensors_device_attribute attr_min;
++ char *attr_min_name;
++ struct ipmisensors_device_attribute attr_max;
++ char *attr_max_name;
++ struct ipmisensors_device_attribute attr_label;
++ char *attr_label_name;
++
++};
++
++/**
++ * &struct_ipmisensors_data stores the data for the ipmisensors driver.
++ */
++struct ipmisensors_data {
++ /* Driver struct */
++ char *driver_name;
++
++ /* Linked list of ipmisensors_bmc_data structs, one for each BMC */
++ struct list_head bmc_data;
++
++ /* Number of ipmi interfaces (and hence ipmisensors_data structs). */
++ int interfaces;
++
++ /* IPMI kernel interface - SMI watcher */
++ struct ipmi_smi_watcher smi_watcher;
++
++ /* IPMI kernel interface - user handlers */
++ struct ipmi_user_hndl ipmi_hndlrs;
++
++ /* Cache manager for sdrdata cache */
++ struct kmem_cache *sdrdata_cache;
++
++ /* Cache manager for ipmi_sensor_device_attribute cache */
++ struct kmem_cache *sysfsattr_cache;
++};
++
++/**
++ * &states: enumeration of state codes for a bmc specific ipmisensors
++ */
++enum states {
++ STATE_INIT,
++ STATE_RESERVE,
++ STATE_SDR,
++ STATE_SDRPARTIAL,
++ STATE_READING,
++ STATE_UNCANCEL,
++ STATE_SYSTABLE,
++ STATE_DONE
++};
++
++/**
++ * &struct_ipmisensors_bmc_data stores the data for a particular IPMI BMC.
++ */
++struct ipmisensors_bmc_data {
++ struct list_head list;
++
++ /* The IPMI interface number */
++ int interface_id;
++
++ /* The IPMI address */
++ struct ipmi_addr address;
++
++ /* List of sdrdata structs (sdrs) recieved from the BMC */
++ struct list_head sdrs;
++
++ /* Count of the number of sdrs stored in the sdr list */
++ int sdr_count;
++
++ /* next message id */
++ int msgid;
++
++ /* The ipmi interface 'user' used to access this particular bmc */
++ ipmi_user_t user;
++
++ /* BMC IPMI Version (major) */
++ unsigned char ipmi_version_major;
++
++ /* BMC IPMI Version (minor) */
++ unsigned char ipmi_version_minor;
++
++ /* The size of the SDR request message */
++ int ipmi_sdr_partial_size;
++
++ /* transmit message buffer */
++ struct kernel_ipmi_msg tx_message;
++
++ /* ipmi transmited data buffer */
++ unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; /* why the +50 in bmcsensors? */
++
++ /* ipmi recieved data buffer */
++ unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH + 50];
++
++ /* current recieve buffer offset */
++ int rx_msg_data_offset;
++
++ /* The id of then next SDR record to read during update cycle */
++ u16 nextrecord;
++
++ /* BMC SDR Reservation ID */
++ u16 resid;
++
++ /* Alarm status */
++ u8 alarms;
++
++ /* The cumalative error count for this bmc */
++ int errorcount;
++
++ /* The current state of this bmc w.r.t. ipmisensors (see enum states) */
++ int state;
++
++ /* The current sdr for which a reading is pending */
++ struct sdrdata *current_sdr;
++
++ /* The BMC's device struct */
++ struct device *dev;
++
++ /* hwmon class device */
++ struct class_device *class_dev;
++
++ /* hwmon device name */
++ struct device_attribute name_attr;
++
++ /* alarms attribute */
++ struct ipmisensors_bmc_device_attribute alarms_attr;
++
++ /* update_period attribute */
++ struct ipmisensors_bmc_device_attribute update_attr;
++
++ /* lower bound on time between updates (in seconds) */
++ unsigned int update_period;
++
++ /* semaphore used to do a headcount of the SDR readings we are waiting
++ * on in a given bmc update */
++ struct semaphore update_semaphore;
++
++ /* bmc's work struct for updating sensors */
++ struct delayed_work update_work;
++
++ /* bmc's work struct for building the sysfs workqueue */
++ struct work_struct sysfs_work;
++};
+diff -rduNp linux-2.6.22.1.oorig2/include/linux/ipmi.h linux-2.6.22.1/include/linux/ipmi.h
+--- linux-2.6.22.1.oorig2/include/linux/ipmi.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/include/linux/ipmi.h 2007-07-24 14:22:26.000000000 +0200
+@@ -300,6 +300,9 @@ int ipmi_create_user(unsigned int
+ safe, too. */
+ int ipmi_destroy_user(ipmi_user_t user);
+
++/* Get the IPMI BMC's device struct */
++struct device *ipmi_get_bmcdevice(int ipmi_intf);
++
+ /* Get the IPMI version of the BMC we are talking to. */
+ void ipmi_get_version(ipmi_user_t user,
+ unsigned char *major,
+diff -rduNp linux-2.6.22.1.oorig2/include/linux/ipmi_msgdefs.h linux-2.6.22.1/include/linux/ipmi_msgdefs.h
+--- linux-2.6.22.1.oorig2/include/linux/ipmi_msgdefs.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/include/linux/ipmi_msgdefs.h 2007-07-24 14:22:26.000000000 +0200
+@@ -45,6 +45,7 @@
+
+ #define IPMI_NETFN_APP_REQUEST 0x06
+ #define IPMI_NETFN_APP_RESPONSE 0x07
++#define IPMI_GET_DEVICE_GUID_CMD 0x08
+ #define IPMI_GET_DEVICE_ID_CMD 0x01
+ #define IPMI_COLD_RESET_CMD 0x02
+ #define IPMI_WARM_RESET_CMD 0x03
+@@ -57,6 +58,11 @@
+ #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
+ #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
+ #define IPMI_GET_CHANNEL_INFO_CMD 0x42
++#define IPMI_RESERVE_SDR 0x22
++#define IPMI_GET_SDR 0x23
++#define IPMI_GET_SENSOR_STATE_READING 0x2D
++#define IPMI_SET_SENSOR_HYSTERESIS 0x24
++#define IPMI_SET_SENSOR_THRESHOLD 0x26
+
+ #define IPMI_NETFN_STORAGE_REQUEST 0x0a
+ #define IPMI_NETFN_STORAGE_RESPONSE 0x0b
+@@ -79,10 +85,13 @@
+ #define IPMI_NODE_BUSY_ERR 0xc0
+ #define IPMI_INVALID_COMMAND_ERR 0xc1
+ #define IPMI_TIMEOUT_ERR 0xc3
++#define IPMI_INVALID_RESERVATION_ID 0xc5
+ #define IPMI_ERR_MSG_TRUNCATED 0xc6
+ #define IPMI_REQ_LEN_INVALID_ERR 0xc7
+ #define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
+ #define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
++#define IPMI_ERR_RETURNING_REQ_BYTES 0xca
++#define IPMI_ERR_PROVIDING_RESPONSE 0xce
+ #define IPMI_LOST_ARBITRATION_ERR 0x81
+ #define IPMI_BUS_ERR 0x82
+ #define IPMI_NAK_ON_WRITE_ERR 0x83
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.9-007-ipmisensors-20070314-1214.patch b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.9-007-ipmisensors-20070314-1214.patch
new file mode 100644
index 0000000000..5fe74954f3
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/ipmi/linux-2.6.22.9-007-ipmisensors-20070314-1214.patch
@@ -0,0 +1,1914 @@
+diff -rduNp linux-2.6.22.1.oorig2/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.22.1/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.22.1.oorig2/drivers/char/ipmi/ipmi_msghandler.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/char/ipmi/ipmi_msghandler.c 2007-07-24 14:22:26.000000000 +0200
+@@ -1953,6 +1953,24 @@ static void remove_proc_entries(ipmi_smi
+ #endif /* CONFIG_PROC_FS */
+ }
+
++/*
++ * Retrieves the bmc_device struct for a given ipmi interface number (or NULL if none).
++ */
++struct device *ipmi_get_bmcdevice(int if_num)
++{
++ ipmi_smi_t intf;
++ mutex_lock(&ipmi_interfaces_mutex);
++ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
++ if (intf->intf_num == if_num){
++ mutex_unlock(&ipmi_interfaces_mutex);
++ return &intf->bmc->dev->dev;
++ }
++ }
++ mutex_unlock(&ipmi_interfaces_mutex);
++
++ return NULL;
++}
++
+ static int __find_bmc_guid(struct device *dev, void *data)
+ {
+ unsigned char *id = data;
+@@ -4196,3 +4214,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN);
+ EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+ EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+ EXPORT_SYMBOL(ipmi_free_recv_msg);
++EXPORT_SYMBOL(ipmi_get_bmcdevice);
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/Kconfig linux-2.6.22.1/drivers/hwmon/Kconfig
+--- linux-2.6.22.1.oorig2/drivers/hwmon/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/hwmon/Kconfig 2007-07-24 14:22:26.000000000 +0200
+@@ -248,6 +248,16 @@ config SENSORS_CORETEMP
+ sensor inside your CPU. Supported all are all known variants
+ of Intel Core family.
+
++config SENSORS_IPMI
++ tristate "IPMI Hardware Monitoring Support"
++ depends on HWMON && IPMI_HANDLER && EXPERIMENTAL
++ help
++ If you say yes here you get support for sensors monitored by
++ an IPMI baseboard management controller (BMC).
++
++ This driver can also be built as a module. If so, the module
++ will be called ipmisensors.
++
+ config SENSORS_IT87
+ tristate "ITE IT87xx and compatibles"
+ depends on I2C
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/Makefile linux-2.6.22.1/drivers/hwmon/Makefile
+--- linux-2.6.22.1.oorig2/drivers/hwmon/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/hwmon/Makefile 2007-07-24 14:22:26.000000000 +0200
+@@ -32,6 +32,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
+ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
++obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o
+ obj-$(CONFIG_SENSORS_IT87) += it87.o
+ obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
+ obj-$(CONFIG_SENSORS_LM63) += lm63.o
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.c linux-2.6.22.1/drivers/hwmon/ipmisensors.c
+--- linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/drivers/hwmon/ipmisensors.c 2007-07-24 14:22:26.000000000 +0200
+@@ -0,0 +1,1552 @@
++/*
++ * ipmisensors.c - lm-sensors/hwmon interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/init.h>
++#include <linux/module.h>
++#include <linux/param.h>
++#include <linux/hwmon.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/device.h>
++#include <linux/hwmon.h>
++
++#include "ipmisensors.h"
++
++/****** Function Prototypes ******/
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg);
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc);
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset);
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index);
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr);
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data);
++static int ipmisensors_intf_registered(int ipmi_intf);
++static int ipmisensors_bmc_registered(struct device *bmc);
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address);
++static void ipmisensors_unregister_bmc(int ipmi_intf);
++static void ipmisensors_unregister_bmc_all(void);
++static void ipmisensors_new_smi(int if_num, struct device *dev);
++static void ipmisensors_smi_gone(int if_num);
++static void ipmisensors_update_bmc(struct work_struct *);
++static void ipmisensors_cleanup(void);
++
++/****** Static Vars ******/
++
++/* set when module is being removed */
++static int cleanup = 0;
++
++/* ipmisensors driver data */
++static struct ipmisensors_data driver_data = {
++ .driver_name = "bmc",
++ .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data),
++ .interfaces = 0,
++ .smi_watcher = {
++ .owner = THIS_MODULE,
++ .new_smi = ipmisensors_new_smi,
++ .smi_gone = ipmisensors_smi_gone,
++ },
++ .ipmi_hndlrs = {
++ .ipmi_recv_hndl = ipmisensors_msg_handler,
++ },
++};
++
++/* sensor refresh workqueue */
++static struct workqueue_struct *ipmisensors_workqueue;
++
++/****** SDR List Functions ******/
++/**
++ * Creates a new sdrdata struct, or returns NULL if insufficient memory.
++ */
++static struct sdrdata *ipmisensors_new_sdr(void)
++{
++ struct sdrdata *sdr;
++
++ sdr = kmem_cache_alloc(driver_data.sdrdata_cache, GFP_ATOMIC);
++ if (sdr) {
++ memset(sdr, 0, sizeof(struct sdrdata));
++ } else {
++ printk(KERN_ERR
++ "ipmisensors: Couldn't allocate memory for new SDR\n");
++ }
++
++ return sdr;
++}
++
++/**
++ * Adds the given sdrdata struct to the given bmc's SDR list.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static inline void ipmisensors_add_sdr(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ list_add(&sdr->list, &bmc->sdrs);
++ printk(KERN_DEBUG
++ "ipmisensors: SDR %d: type 0x%02x (%s)\n",
++ bmc->sdr_count, sdr->stype, sdr->id);
++ bmc->sdr_count++;
++}
++
++/**
++ * Cleanup the sdr list for the given BMC.
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_sdr_cleanup(struct ipmisensors_bmc_data *bmc)
++{
++ struct sdrdata *cursor, *next;
++
++ /* find and free each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ device_remove_file(bmc->dev, &cursor->attr.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_min.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_max.dev_attr);
++ device_remove_file(bmc->dev, &cursor->attr_label.dev_attr);
++
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++
++ list_del(&cursor->list);
++ kmem_cache_free(driver_data.sdrdata_cache, cursor);
++ }
++}
++
++/* worker function for workqueue ipmisensors_workqueue */
++static void ipmisensors_update_bmc(struct work_struct *work)
++{
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, update_work.work);
++
++ /* don't start an update cycle if one already in progress */
++ if (bmc->state != STATE_READING) {
++ struct sdrdata *cursor, *next;
++ bmc->state = STATE_READING;
++ printk(KERN_DEBUG "ipmisensors: starting update\n");
++
++ /* init semaphore to 1 for update cycle */
++ sema_init(&bmc->update_semaphore, 1);
++
++ /* update each sdr reading */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ ipmisensors_get_reading(bmc, cursor);
++ }
++ }
++
++ /* wait for readings (need timeout?) */
++ down_interruptible(&bmc->update_semaphore);
++
++ printk(KERN_DEBUG "ipmisensors: update complete\n");
++
++ bmc->state = STATE_DONE;
++
++ /* if the module isn't cleaning up, schedule another update */
++ if (!cleanup)
++ queue_delayed_work(ipmisensors_workqueue, &bmc->update_work,
++ bmc->update_period * HZ);
++}
++
++/****** IPMI Message Sending ******/
++
++/**
++ * Send a message to the IPMI BMC
++ *
++ * @bmc: the bmc to send the message to.
++ * @msgid: the message id to use.
++ * @msg: the ipmi message structure.
++ */
++static void ipmisensors_send_message(struct ipmisensors_bmc_data *bmc,
++ long msgid, struct kernel_ipmi_msg *msg)
++{
++ if (msg->data == NULL)
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x\n", msg->cmd);
++ else
++ printk(KERN_DEBUG "ipmisensors: Send 0x%x 0x%x 0x%x\n",
++ msg->cmd, msg->data[0], msg->data[1]);
++
++ /* This should be ipmi_request, but Corey had to remove
++ * that due to it being unused at the moment, as soon as
++ * this makes it into the kernel we should request it be re-instated.
++ */
++ ipmi_request_settime(bmc->user, &bmc->address, msgid, msg, bmc, 0,
++ -1, 0);
++}
++
++/**
++ * Compose and send a "reserve SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ */
++static void ipmisensors_reserve_sdr(struct ipmisensors_bmc_data *bmc)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_RESERVE_SDR;
++ bmc->tx_message.data_len = 0;
++ bmc->tx_message.data = NULL;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Componse and send a "get SDR" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @res_id:
++ * @record:
++ * @offset:
++ */
++static void ipmisensors_get_sdr(struct ipmisensors_bmc_data *bmc, u16 res_id,
++ u16 record, u8 offset)
++{
++ printk(KERN_DEBUG "ipmisensors: Get SDR 0x%x 0x%x 0x%x\n",
++ res_id, record, offset);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SDR;
++ bmc->tx_message.data_len = 6;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = res_id & 0xff;
++ bmc->tx_msg_data[1] = res_id >> 8;
++ bmc->tx_msg_data[2] = record & 0xff;
++ bmc->tx_msg_data[3] = record >> 8;
++ bmc->tx_msg_data[4] = offset;
++ bmc->tx_msg_data[5] = bmc->ipmi_sdr_partial_size;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "set sensor threshold" message
++ *
++ * @bmc: the bmc to send the message to.
++ * @id: the ipmi id number of the sensor.
++ * @value: the new value for the threshold.
++ * @lim_index: the index in the lim[] array for which this value applies.
++ */
++static void ipmisensors_set_sensor_threshold(struct ipmisensors_bmc_data *bmc,
++ u8 number, int value,
++ int lim_index)
++{
++ int i;
++
++ printk(KERN_DEBUG "ipmisensors: Set SDR Threshold %d %d %d\n",
++ number, value, lim_index);
++ bmc->tx_message.netfn = IPMI_NETFN_STORAGE_REQUEST;
++ bmc->tx_message.cmd = IPMI_SET_SENSOR_THRESHOLD;
++ bmc->tx_message.data_len = 8;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = number & 0xff;
++ bmc->tx_msg_data[1] = 0x01 << lim_index;
++
++ if (lim_index > 5 || lim_index < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Error - ipmisensors_set_sensor_threshold given invalid lim_index\n");
++ return;
++ }
++
++ for (i = 2; i < 8; i++)
++ bmc->tx_msg_data[i] = 0x00;
++
++ bmc->tx_msg_data[lim_index] = value && 0xff;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++}
++
++/**
++ * Compose and send a "get sensor reading" message for the given sdr.
++ *
++ * @bmc: the bmc to send the message to.
++ * @sdr: the sdr of the sensor to get the reading for.
++ */
++static void ipmisensors_get_reading(struct ipmisensors_bmc_data *bmc,
++ struct sdrdata *sdr)
++{
++ bmc->tx_message.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
++ bmc->tx_message.cmd = IPMI_GET_SENSOR_STATE_READING;
++ bmc->tx_message.data_len = 1;
++ bmc->tx_message.data = bmc->tx_msg_data;
++ bmc->tx_msg_data[0] = sdr->number;
++ bmc->current_sdr = sdr;
++
++ ipmisensors_send_message(bmc, bmc->msgid++, &bmc->tx_message);
++ down_interruptible(&bmc->update_semaphore);
++}
++
++/****** IPMI Message Receiving ******/
++
++/**
++ * Process an sensor reading response message.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_reading_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ struct sdrdata *sdr = bmc->current_sdr;
++
++ if (sdr == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error ipmisensors_rcv_reading with NULL sdr\n");
++ return;
++ }
++
++ sdr->reading = msg->data[1];
++ sdr->status = msg->data[2];
++ sdr->thresholds = msg->data[3];
++
++ printk(KERN_DEBUG "ipmisensors: sensor %d (type %d) reading %d\n",
++ sdr->number, sdr->stype, msg->data[1]);
++
++ up(&bmc->update_semaphore);
++}
++
++/**
++ * Unpack based on string type, convert to normal, null terminate.
++ */
++static void ipmisensors_sprintf(u8 * to, u8 * from, u8 type, u8 length)
++{
++ static const u8 *bcdplus = "0123456789 -.:,_";
++ int i;
++
++ switch (type) {
++ case 0: /* unicode */
++ for (i = 0; i < length; i++)
++ *to++ = (*from++ & 0x7f);
++ *to = 0;
++ break;
++ case 1: /* BCD Plus */
++ for (i = 0; i < length; i++)
++ *to++ = bcdplus[*from++ & 0x0f];
++ *to = 0;
++ break;
++ case 2: /* packed ascii *//* if not a mult. of 3 this will run over */
++ for (i = 0; i < length; i += 3) {
++ *to++ = *from & 0x3f;
++ *to++ = *from >> 6 | ((*(from+1) & 0xf) << 2);
++ from++;
++ *to++ = *from >> 4 | ((*(from+1) & 0x3) << 4);
++ from++;
++ *to++ = (*from++ >> 2) & 0x3f;
++ }
++ *to = 0;
++ break;
++ case 3: /* normal */
++ if (length > 1)
++ memcpy(to, from, length);
++ to[length] = 0;
++ break;
++ }
++}
++
++/* IPMI V1.5 Section 30 */
++static const int exps[] =
++ { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
++
++/* Return 0 for fan, 2 for temp, 3 for voltage
++ We could make it variable based on the accuracy (= log10(m * 10**k2));
++ this would work for /proc output, however libsensors resolution
++ is statically set in lib/chips.c */
++static int decplaces(struct sdrdata *sd)
++{
++ switch (sd->stype) {
++ case STYPE_TEMP:
++ return 2;
++ case STYPE_CURR:
++ case STYPE_VOLT:
++ return 3;
++ case STYPE_FAN:
++ default:
++ return 0;
++ }
++}
++
++/* convert a raw value to a reading. IMPI V1.5 Section 30 */
++static long conv_val(int value, struct sdrdata *sd)
++{
++ u8 k1, k2;
++ long r;
++
++ r = value * sd->m;
++ k1 = sd->k & 0x0f;
++ k2 = sd->k >> 4;
++ if (k1 < 8)
++ r += sd->b * exps[k1];
++ else
++ r += sd->b / exps[16 - k1];
++ r *= exps[decplaces(sd)];
++ if (k2 < 8) {
++ if (sd->linear != 7)
++ r *= exps[k2];
++ else
++ /* this will always truncate to 0: r = 1 / (exps[k2] * r); */
++ r = 0;
++ } else {
++ if (sd->linear != 7)
++ r /= exps[16 - k2];
++ else {
++ if (r != 0)
++ /* 1 / x * 10 ** (-m) == 10 ** m / x */
++ r = exps[16 - k2] / r;
++ else
++ r = 0;
++ }
++ }
++
++ return r;
++}
++
++static const char *threshold_text[] = {
++ "upper non-recoverable threshold",
++ "upper critical threshold",
++ "upper non-critical threshold",
++ "lower non-recoverable threshold",
++ "lower critical threshold",
++ "lower non-critical threshold",
++ "positive-going hysteresis",
++ "negative-going hysteresis" /* unused */
++};
++
++/* select two out of the 8 possible readable thresholds, and place indexes into the limits
++ array into lim1 and lim2. Set writable flags */
++static void ipmisensors_select_thresholds(struct sdrdata *sd)
++{
++ u8 capab = sd->capab;
++ u16 mask = sd->thresh_mask;
++ int tmp;
++
++ sd->lim1 = -1;
++ sd->lim2 = -1;
++ sd->lim1_write = 0;
++ sd->lim2_write = 0;
++
++ if (((capab & 0x0c) == 0x04) || /* readable thresholds ? */
++ ((capab & 0x0c) == 0x08)) {
++ /* select upper threshold */
++ if (mask & 0x10) { /* upper crit */
++ sd->lim1 = 1;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x1000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x20) { /* upper non-recov */
++ sd->lim1 = 0;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x2000))
++ sd->lim1_write = 1;
++ } else if (mask & 0x08) { /* upper non-crit */
++ sd->lim1 = 2;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0800))
++ sd->lim1_write = 1;
++ }
++
++ /* select lower threshold */
++ if ((((capab & 0x30) == 0x10) || /* readable ? */
++ ((capab & 0x30) == 0x20)) && /* pos hyst */
++ sd->stype == STYPE_TEMP)
++ sd->lim2 = 6;
++ else if (mask & 0x02) { /* lower crit */
++ sd->lim2 = 4;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0200))
++ sd->lim2_write = 1;
++ } else if (mask & 0x04) { /* lower non-recov */
++ sd->lim2 = 3;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0400))
++ sd->lim2_write = 1;
++ } else if (mask & 0x01) { /* lower non-crit */
++ sd->lim2 = 5;
++ if ((capab & 0x0c) == 0x08 && (mask & 0x0100))
++ sd->lim2_write = 1;
++ }
++ }
++
++ /* swap lim1/lim2 if m < 0 or function is 1/x (but not both!) */
++ if ((sd->m < 0 && sd->linear != 7) || (sd->m >= 0 && sd->linear == 7)) {
++ tmp = sd->lim1;
++ sd->lim1 = sd->lim2;
++ sd->lim2 = tmp;
++ }
++
++ if (sd->lim1 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for upper limit\n",
++ threshold_text[sd->lim1]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable upper limit\n");
++
++ if (sd->lim2 >= 0)
++ printk(KERN_INFO "ipmisensors: using %s for lower limit\n",
++ threshold_text[sd->lim2]);
++ else
++ printk(KERN_DEBUG "ipmisensors: no readable lower limit\n");
++}
++
++/************* sysfs callback functions *********/
++static ssize_t show_update_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ return snprintf(buf, 20, "%d\n", aattr->bmc->update_period);
++}
++
++static ssize_t store_update_period(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++
++ aattr->bmc->update_period = simple_strtoul(buf, NULL, 10);;
++ return count;
++};
++
++static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ return snprintf(buf, 20, "%ld\n",
++ conv_val(sattr->sdr->reading, sattr->sdr));
++}
++
++static ssize_t show_sensor_max(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long max = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim1 >= 0)
++ max = conv_val(sattr->sdr->limits[sattr->sdr->lim1],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", max);
++}
++
++static ssize_t show_sensor_min(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ long min = 0;
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ if (sattr->sdr->lim2 >= 0)
++ min = conv_val(sattr->sdr->limits[sattr->sdr->lim2],
++ sattr->sdr);
++ return snprintf(buf, 20, "%ld\n", min);
++};
++
++static ssize_t show_sensor_label(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ u8 label[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++
++ ipmisensors_sprintf(label, sattr->sdr->id, sattr->sdr->string_type,
++ sattr->sdr->id_length);
++ return snprintf(buf, 20, "%s\n", label);
++};
++
++static ssize_t store_sensor_max(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set max on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim1);
++ return count;
++};
++
++static ssize_t store_sensor_min(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ long val = simple_strtoul(buf, NULL, 10);
++ struct ipmisensors_device_attribute *sattr =
++ to_ipmisensors_dev_attr(attr);
++ printk(KERN_DEBUG "ipmisensors: set min on sensor #%d to %ld",
++ sattr->sdr->number, val);
++ ipmisensors_set_sensor_threshold(sattr->sdr->bmc, sattr->sdr->number,
++ val, sattr->sdr->lim2);
++ return count;
++};
++
++static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ipmisensors_bmc_device_attribute *aattr =
++ to_ipmisensors_bmc_dev_attr(attr);
++ return snprintf(buf, 20, "%d\n", aattr->bmc->alarms);
++};
++
++static ssize_t show_name(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return snprintf(buf, 20, "%s\n", driver_data.driver_name);
++};
++
++/* work function to build the sysfs entries using the ipmi sdrs */
++static void ipmisensors_build_sysfs(struct work_struct *work)
++{
++ int temps = 0, volts = 0, currs = 0, fans = 0;
++ struct sdrdata *cursor, *next;
++ struct ipmisensors_bmc_data *bmc = container_of(work, struct ipmisensors_bmc_data, sysfs_work);
++
++ /* find and create entries for each sdr data struct */
++ list_for_each_entry_safe(cursor, next, &bmc->sdrs, list) {
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++
++ cursor->attr_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_max_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++ cursor->attr_min_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label_name =
++ (char *)kmalloc(sizeof(char) * MAX_FILENAME_LENGTH,
++ GFP_KERNEL);
++
++ if (cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ return;
++ }
++ }
++
++ if (cursor->attr_name == NULL || cursor->attr_max_name == NULL
++ || cursor->attr_min_name == NULL
++ || cursor->attr_label_name == NULL) {
++ printk(KERN_INFO
++ "ipmisensors: Out of memory (kmalloc failed)");
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "temp%d_input", ++temps);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "temp%d_max", temps);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "temp%d_min", temps);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "temp%d_label", temps);
++ break;
++ case (STYPE_VOLT):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "in%d_input", ++volts);
++ /* create min, max attributes */
++ snprintf(cursor->attr_max_name, MAX_FILENAME_LENGTH,
++ "in%d_max", volts);
++ snprintf(cursor->attr_min_name, MAX_FILENAME_LENGTH,
++ "in%d_min", volts);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "in%d_label", volts);
++ break;
++ case (STYPE_CURR):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "curr%d_input", ++currs);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "curr%d_max", currs);
++ sprintf(cursor->attr_min_name, "curr%d_min", currs);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "curr%d_label", currs);
++ break;
++ case (STYPE_FAN):
++ /* create the name of the sensor */
++ snprintf(cursor->attr_name, MAX_FILENAME_LENGTH,
++ "fan%d_input", ++fans);
++ /* create min, max attributes */
++ sprintf(cursor->attr_max_name, "fan%d_max", fans);
++ sprintf(cursor->attr_min_name, "fan%d_min", fans);
++ /* create the label of the sensor */
++ snprintf(cursor->attr_label_name, MAX_FILENAME_LENGTH,
++ "fan%d_label", fans);
++ break;
++ default:
++ printk(KERN_INFO "ipmisensors: unkown sensor type\n");
++ continue;
++ }
++
++ cursor->attr.dev_attr.attr.name = cursor->attr_name;
++ cursor->attr.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr.dev_attr.show = show_sensor;
++ cursor->attr.dev_attr.store = NULL;
++ cursor->attr.sdr = cursor;
++
++ cursor->attr_min.dev_attr.attr.name = cursor->attr_min_name;
++ cursor->attr_min.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_min.dev_attr.show = show_sensor_min;
++ cursor->attr_min.sdr = cursor;
++
++ if (cursor->lim2_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_min.dev_attr.store = store_sensor_min;
++ cursor->attr_min.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_min.dev_attr.store = NULL;
++ cursor->attr_min.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ cursor->attr_max.dev_attr.attr.name = cursor->attr_max_name;
++ cursor->attr_max.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_max.dev_attr.show = show_sensor_max;
++ cursor->attr_max.sdr = cursor;
++
++ if (cursor->lim1_write) {
++ printk(KERN_INFO
++ "ipmisensors: You have a writable sensor threshold! Send me an e-mail at <yani.ioannou@gmail.com>.\n");
++ cursor->attr_max.dev_attr.store = store_sensor_max;
++ cursor->attr_max.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ } else {
++ cursor->attr_max.dev_attr.store = NULL;
++ cursor->attr_max.dev_attr.attr.mode = S_IRUGO;
++ }
++
++ if (cursor->id_length > 0) {
++ cursor->attr_label.dev_attr.attr.name =
++ cursor->attr_label_name;
++ cursor->attr_label.dev_attr.attr.mode = S_IRUGO;
++ cursor->attr_label.dev_attr.attr.owner = THIS_MODULE;
++ cursor->attr_label.dev_attr.show = show_sensor_label;
++ cursor->attr_label.dev_attr.store = NULL;
++ cursor->attr_label.sdr = cursor;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registering sensor %d: (type 0x%.2x) "
++ "(fmt=%d; m=%d; b=%d; k1=%d; k2=%d; cap=0x%.2x; mask=0x%.4x)\n",
++ cursor->number, cursor->stype, cursor->format, cursor->m,
++ cursor->b, cursor->k & 0xf, cursor->k >> 4,
++ cursor->capab, cursor->thresh_mask);
++
++ if (cursor->id_length > 0) {
++ ipmisensors_sprintf(id, cursor->id, cursor->string_type,
++ cursor->id_length);
++ switch (cursor->stype) {
++ case (STYPE_TEMP):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label temp%d \"%s\"\n",
++ temps, id);
++ break;
++ case (STYPE_VOLT):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label in%d \"%s\"\n",
++ volts, id);
++ break;
++ case (STYPE_CURR):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label curr%d \"%s\"\n",
++ currs, id);
++ break;
++ case (STYPE_FAN):
++ printk(KERN_INFO
++ "ipmisensors: sensors.conf: label fan%d \"%s\"\n",
++ fans, id);
++ break;
++ }
++ }
++
++ ipmisensors_select_thresholds(cursor);
++
++ if (cursor->linear != 0 && cursor->linear != 7) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: nonlinear function 0x%.2x unsupported, expect bad results\n",
++ cursor->number, cursor->linear);
++ }
++
++ if ((cursor->format & 0x03) == 0x02) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: 1's complement format unsupported, expect bad results\n",
++ cursor->number);
++ } else if ((cursor->format & 0x03) == 0x03) {
++ printk(KERN_INFO
++ "ipmisensors: sensor %d: threshold sensor only, no readings available",
++ cursor->number);
++ }
++
++ if (cursor->lim1_write || cursor->lim2_write)
++ cursor->attr.dev_attr.attr.mode = 0644;
++ else
++ cursor->attr.dev_attr.attr.mode = 0444;
++
++ if (device_create_file(bmc->dev, &cursor->attr.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_min.dev_attr) < 0
++ || device_create_file(bmc->dev,
++ &cursor->attr_max.dev_attr) < 0
++ || (cursor->id_length >
++ 0 ? device_create_file(bmc->dev,
++ &cursor->attr_label.dev_attr) <
++ 0 : 0)
++ ) {
++ printk(KERN_INFO
++ "ipmisensors: sysfs file creation failed for SDR %d (%s).\n",
++ cursor->number, cursor->id);
++ kfree(cursor->attr_name);
++ kfree(cursor->attr_max_name);
++ kfree(cursor->attr_min_name);
++ kfree(cursor->attr_label_name);
++ return;
++ }
++ }
++
++ bmc->alarms_attr.dev_attr.attr.name = "alarms";
++ bmc->alarms_attr.dev_attr.attr.mode = S_IRUGO;
++ bmc->alarms_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->alarms_attr.dev_attr.show = show_alarms;
++ bmc->alarms_attr.dev_attr.store = NULL;
++ bmc->alarms_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->alarms_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'alarms'");
++ return;
++ }
++
++ bmc->name_attr.attr.name = "name";
++ bmc->name_attr.attr.mode = S_IRUGO;
++ bmc->name_attr.attr.owner = THIS_MODULE;
++ bmc->name_attr.show = show_name;
++
++ if (device_create_file(bmc->dev, &bmc->name_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'name'");
++ return;
++ }
++
++ bmc->update_attr.dev_attr.attr.name = "update_period";
++ bmc->update_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
++ bmc->update_attr.dev_attr.attr.owner = THIS_MODULE;
++ bmc->update_attr.dev_attr.show = show_update_period;
++ bmc->update_attr.dev_attr.store = store_update_period;
++ bmc->update_attr.bmc = bmc;
++
++ if (device_create_file(bmc->dev, &bmc->update_attr.dev_attr) < 0) {
++ printk(KERN_INFO
++ "ipmisensors: Failed to create sysfs entry 'update_period'");
++ return;
++ }
++
++ printk(KERN_INFO
++ "ipmisensors: registered %d temp, %d volt, %d current, %d fan sensors\n",
++ temps, volts, currs, fans);
++
++ /* This completes the initialization. We can now kickoff the
++ * periodic update of the bmc sensor's values by scheduling
++ * the first work.
++ */
++ queue_work(ipmisensors_workqueue, &bmc->update_work.work);
++
++}
++
++/**
++ * Process an SDR response message, save the SDRs we like in the sdr
++ * list for the given BMC.
++ *
++ * @bmc: the bmc the message is from
++ * @msg: the IPMI SDR response message
++ */
++static void ipmisensors_rcv_sdr_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ u16 record;
++ int type;
++ int stype;
++ int id_length;
++ int i;
++ int ipmi_ver = 0;
++ unsigned char *data;
++ u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
++ struct sdrdata *sdr;
++
++ if (msg->data[0] != 0) {
++ /* cut request in half and try again */
++ bmc->ipmi_sdr_partial_size /= 2;
++ if (bmc->ipmi_sdr_partial_size < 8) {
++ printk(KERN_INFO
++ "ipmisensors: IPMI buffers too small, giving up\n");
++ bmc->state = STATE_DONE;
++ return;
++ }
++ printk(KERN_DEBUG
++ "ipmisensors: Reducing SDR request size to %d\n",
++ bmc->ipmi_sdr_partial_size);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ if (bmc->ipmi_sdr_partial_size < IPMI_SDR_SIZE) {
++ if (bmc->rx_msg_data_offset == 0) {
++ memcpy(bmc->rx_msg_data, msg->data,
++ bmc->ipmi_sdr_partial_size + 3);
++ bmc->rx_msg_data_offset =
++ bmc->ipmi_sdr_partial_size + 3;
++ } else {
++ memcpy(bmc->rx_msg_data + bmc->rx_msg_data_offset,
++ msg->data + 3, bmc->ipmi_sdr_partial_size);
++ bmc->rx_msg_data_offset += bmc->ipmi_sdr_partial_size;
++ }
++ if (bmc->rx_msg_data_offset > bmc->rx_msg_data[7] + 7) {
++ /* got last chunk */
++ bmc->rx_msg_data_offset = 0;
++ data = bmc->rx_msg_data;
++ } else {
++ /* get more */
++ record =
++ (bmc->rx_msg_data[4] << 8) | bmc->rx_msg_data[3];
++ ipmisensors_get_sdr(bmc, bmc->resid, record,
++ bmc->rx_msg_data_offset - 3);
++ bmc->state = STATE_SDR;
++ return;
++ }
++ } else {
++ /* got it in one chunk */
++ data = msg->data;
++ }
++
++ bmc->nextrecord = (data[2] << 8) | data[1];
++
++ /* If the ipmi version is 0.9 we have to remap some things.
++ * Yes this is very ugly, but we aren't the ones who
++ * implemented an incomplete spec!
++ */
++ ipmi_ver = data[5];
++
++ type = data[6];
++ /* known SDR type */
++ if (type == 1 || type == 2) {
++ stype = data[(ipmi_ver == 0x90 ? 16 : 15)];
++ /* known sensor type */
++ if (stype <= STYPE_MAX) {
++ if (data[(ipmi_ver == 0x90 ? 17 : 16)] != 0x01) {
++ if (type == 1)
++ ipmisensors_sprintf(id, &data[51],
++ data[50] >> 6,
++ data[50] & 0x1f);
++ else
++ ipmisensors_sprintf(id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 :
++ 35)],
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] >> 6,
++ data[(ipmi_ver ==
++ 0x90 ? 29 :
++ 34)] & 0x1f);
++ printk(KERN_INFO
++ "ipmisensors: skipping non-threshold sensor \"%s\"\n",
++ id);
++ } else {
++ /* add entry to sdrd table */
++ sdr = ipmisensors_new_sdr();
++ if (!sdr) {
++ printk(KERN_ERR
++ "ipmisensors: could not allocate memory for new SDR");
++ return;
++ }
++ sdr->bmc = bmc;
++ sdr->stype = stype;
++ sdr->number = data[10];
++ sdr->capab = data[(ipmi_ver == 0x90 ? 15 : 14)];
++ sdr->thresh_mask =
++ (((u16) data[(ipmi_ver == 0x90 ? 21 : 22)])
++ << 8) | data[21];
++ if (type == 1) {
++ sdr->format =
++ data[(ipmi_ver ==
++ 0x90 ? 22 : 24)] >> 6;
++ sdr->linear =
++ data[(ipmi_ver ==
++ 0x90 ? 25 : 26)] & 0x7f;
++ sdr->m =
++ data[(ipmi_ver == 0x90 ? 26 : 27)];
++ sdr->m |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 27 : 28)]
++ & 0xc0)) << 2;
++ if (sdr->m & 0x0200) {
++ /* sign extend */
++ sdr->m |= 0xfc00;
++ }
++ sdr->b =
++ data[(ipmi_ver == 0x90 ? 28 : 29)];
++ sdr->b |= ((u16)
++ (data
++ [(ipmi_ver ==
++ 0x90 ? 29 : 30)]
++ & 0xc0)) << 2;
++ if (sdr->b & 0x0200) {
++ /* sign extend */
++ sdr->b |= 0xfc00;
++ }
++ sdr->k =
++ data[(ipmi_ver == 0x90 ? 31 : 32)];
++ sdr->nominal =
++ data[(ipmi_ver == 0x90 ? 33 : 34)];
++ for (i = 0; i < SDR_LIMITS; i++) {
++ /* assume readable */
++ sdr->limits[i] =
++ data[(ipmi_ver ==
++ 0x90 ? 40 : 39) + i];
++ }
++ sdr->string_type = data[50] >> 6;
++ id_length = data[50] & 0x1f;
++ memcpy(sdr->id, &data[51], id_length);
++ sdr->id_length = id_length;
++ } else {
++ sdr->m = 1;
++ sdr->b = 0;
++ sdr->k = 0;
++ sdr->string_type =
++ data[(ipmi_ver ==
++ 0x90 ? 29 : 34)] >> 6;
++ id_length = data[34] & 0x1f;
++ if (id_length > 0) {
++ memcpy(sdr->id,
++ &data[(ipmi_ver ==
++ 0x90 ? 30 : 35)],
++ id_length);
++ }
++ sdr->id_length = id_length;
++ /* limits?? */
++ if (ipmi_ver == 0x90) {
++ memcpy(sdr->id,
++ &data[30], id_length);
++ sdr->id_length = id_length;
++ }
++ }
++ ipmisensors_add_sdr(bmc, sdr);
++ }
++ }
++ /* peek at the other SDR types */
++ } else if (type == 0x10 || type == 0x11 || type == 0x12) {
++ ipmisensors_sprintf(id, data + 19, data[18] >> 6,
++ data[18] & 0x1f);
++ if (type == 0x10) {
++ printk(KERN_INFO
++ "ipmisensors: Generic Device acc=0x%x; slv=0x%x; lun=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[13], id);
++ } else if (type == 0x11) {
++ printk(KERN_INFO
++ "ipmisensors: FRU Device acc=0x%x; slv=0x%x; log=0x%x; ch=0x%x; type=0x%x; \"%s\"\n",
++ data[8], data[9], data[10], data[11], data[13],
++ id);
++ } else {
++ printk(KERN_INFO
++ "ipmisensors: Mgmt Ctllr Device slv=0x%x; \"%s\"\n",
++ data[8], id);
++ }
++ } else if (type == 0x14) {
++ printk(KERN_INFO
++ "ipmisensors: Message Channel Info Records:\n");
++ for (i = 0; i < 8; i++) {
++ printk(KERN_INFO "ipmisensors: Channel %d info 0x%x\n",
++ i, data[9 + i]);
++ }
++ } else {
++ printk(KERN_INFO "ipmisensors: Skipping SDR type 0x%x\n", type);
++ }
++ if (ipmi_ver != 0x90) {
++ if (bmc->nextrecord >= 6224) {
++ /*YJ stop sensor scan on poweredge 1750 */
++ bmc->nextrecord = 0xffff;
++ }
++ }
++
++ if (bmc->nextrecord == 0xFFFF) {
++ if (bmc->sdr_count == 0) {
++ printk(KERN_INFO
++ "ipmisensors: No recognized sensors found.\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_INFO "ipmisensors: all sensors detected\n");
++ bmc->state = STATE_SYSTABLE;
++
++ /* Schedule sysfs build/registration work */
++ INIT_WORK(&bmc->sysfs_work, ipmisensors_build_sysfs);
++ queue_work(ipmisensors_workqueue, &bmc->sysfs_work);
++ }
++ } else {
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ }
++}
++
++/**
++ * Process incoming messages based on internal state
++ *
++ * @bmc: the bmc the message is from.
++ * @msg: the ipmi message to process.
++ */
++static void ipmisensors_rcv_msg(struct ipmisensors_bmc_data *bmc,
++ struct kernel_ipmi_msg *msg)
++{
++ switch (bmc->state) {
++ case STATE_INIT:
++ case STATE_RESERVE:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got first resid 0x%.4x\n",
++ bmc->resid);
++
++ ipmisensors_get_sdr(bmc, 0, 0, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_SDR:
++ case STATE_SDRPARTIAL:
++ ipmisensors_rcv_sdr_msg(bmc, msg);
++ break;
++
++ case STATE_READING:
++ ipmisensors_rcv_reading_msg(bmc, msg);
++ break;
++
++ case STATE_UNCANCEL:
++ bmc->resid = (((u16) msg->data[2]) << 8) | msg->data[1];
++
++ printk(KERN_DEBUG "ipmisensors: Got new resid 0x%.4x\n",
++ bmc->resid);
++
++ bmc->rx_msg_data_offset = 0;
++ ipmisensors_get_sdr(bmc, 0, bmc->nextrecord, 0);
++ bmc->state = STATE_SDR;
++ break;
++
++ case STATE_DONE:
++ case STATE_SYSTABLE:
++ break;
++ default:
++ bmc->state = STATE_INIT;
++ }
++}
++
++/**
++ * Callback to handle a received IPMI message from a given BMC.
++ *
++ * @msg: the received message.
++ * @handler_data: a pointer to the particular bmc ipmisensors_bmc_data struct.
++ */
++static void ipmisensors_msg_handler(struct ipmi_recv_msg *msg,
++ void *user_msg_data)
++{
++ struct ipmisensors_bmc_data *bmc =
++ (struct ipmisensors_bmc_data *)user_msg_data;
++
++ if (msg->msg.data[0] != 0)
++ printk(KERN_WARNING
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x\n",
++ msg->msg.data[0], msg->msg.netfn, msg->msg.cmd);
++
++ if (bmc != NULL && ipmisensors_intf_registered(bmc->interface_id)) {
++ if (bmc->state == STATE_SDR &&
++ msg->msg.data[0] == IPMI_INVALID_RESERVATION_ID) {
++ /* reservation cancelled, get new resid */
++ if (++bmc->errorcount > 275) {
++ printk(KERN_ERR
++ "ipmisensors: Too many reservations cancelled, giving up\n");
++ bmc->state = STATE_DONE;
++ } else {
++ printk(KERN_DEBUG
++ "ipmisensors: resid 0x%04x cancelled, getting new one\n",
++ bmc->resid);
++
++ ipmisensors_reserve_sdr(bmc);
++ bmc->state = STATE_UNCANCEL;
++ }
++ } else if (msg->msg.data[0] != IPMI_CC_NO_ERROR &&
++ msg->msg.data[0] != IPMI_ERR_RETURNING_REQ_BYTES &&
++ msg->msg.data[0] != IPMI_ERR_PROVIDING_RESPONSE) {
++ printk(KERN_ERR
++ "ipmisensors: Error 0x%x on cmd 0x%x/0x%x; state = %d; probably fatal.\n",
++ msg->msg.data[0], msg->msg.netfn & 0xfe,
++ msg->msg.cmd, bmc->state);
++ } else {
++ printk(KERN_DEBUG "ipmisensors: received message\n");
++ ipmisensors_rcv_msg(bmc, &msg->msg);
++ }
++
++ } else {
++ printk(KERN_WARNING
++ "ipmisensors: Response for non-registered BMC\n");
++ if (bmc != NULL)
++ printk(KERN_DEBUG "ipmisensors: BMC ID: %d\n",
++ bmc->interface_id);
++ else
++ printk(KERN_DEBUG "ipmisensors: BMC NULL!\n");
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++/****** IPMI Interface Initialization ******/
++
++/**
++ * Return true if the given ipmi interface has been registered.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static int ipmisensors_intf_registered(int ipmi_intf)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Return true if the given BMC has been registered.
++ *
++ * @bmc: The BMC device.
++ */
++static int ipmisensors_bmc_registered(struct device *bmc)
++{
++ int found = 0;
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->dev == bmc) {
++ found++;
++ }
++ }
++
++ return found;
++}
++
++/**
++ * Register new IPMI BMC interface. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_register_bmc(int ipmi_intf, struct ipmi_addr *address)
++{
++ int error;
++
++ /* allocate a new ipmisensors_bmc_data struct */
++
++ struct ipmisensors_bmc_data *bmc = (struct ipmisensors_bmc_data *)
++ kmalloc(sizeof(struct ipmisensors_bmc_data), GFP_KERNEL);
++
++ /* initialize members */
++ INIT_LIST_HEAD(&bmc->sdrs);
++ bmc->interface_id = ipmi_intf;
++
++ bmc->address = *address;
++
++ bmc->sdr_count = 0;
++ bmc->msgid = 0;
++ bmc->ipmi_sdr_partial_size = IPMI_CHUNK_SIZE;
++ bmc->state = STATE_INIT;
++ bmc->errorcount = 0;
++ bmc->rx_msg_data_offset = 0;
++ bmc->dev = ipmi_get_bmcdevice(ipmi_intf);
++
++ /* default to 3 second min update interval */
++ bmc->update_period = 3;
++
++ if (bmc->dev == NULL) {
++ printk(KERN_ERR
++ "ipmisensors: Error, couldn't get BMC device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Create IPMI messaging interface user */
++ error = ipmi_create_user(bmc->interface_id, &driver_data.ipmi_hndlrs,
++ bmc, &bmc->user);
++ if (error < 0) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register user with ipmi interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC as a HWMON class device */
++ bmc->class_dev = hwmon_device_register(bmc->dev);
++
++ if (IS_ERR(bmc->class_dev)) {
++ printk(KERN_ERR
++ "ipmisensors: Error, unable to register hwmon class device for interface %d\n",
++ bmc->interface_id);
++ kfree(bmc);
++ return;
++ }
++
++ /* Register the BMC in the driver */
++ if (ipmisensors_bmc_registered(bmc->dev)) {
++ printk(KERN_ERR
++ "ipmisensors: BMC on interface %d already registered\n",
++ bmc->interface_id);
++ hwmon_device_unregister(bmc->class_dev);
++ kfree(bmc);
++ return;
++ }
++
++ ipmi_get_version(bmc->user, &bmc->ipmi_version_major,
++ &bmc->ipmi_version_minor);
++
++ /* finally add the new bmc data to the bmc data list */
++ list_add_tail(&bmc->list, &driver_data.bmc_data);
++ driver_data.interfaces++;
++
++ printk(KERN_INFO
++ "ipmisensors: Registered IPMI %d.%d BMC over interface %d\n",
++ bmc->ipmi_version_major,
++ bmc->ipmi_version_minor, bmc->interface_id);
++
++ /* Send a reserve SDR command to the bmc */
++ ipmisensors_reserve_sdr(bmc);
++
++ /* initialize the bmc's update work struct */
++ INIT_DELAYED_WORK(&bmc->update_work, ipmisensors_update_bmc);
++}
++
++/**
++ * Callback for when an IPMI BMC is gone. Interface indpendent callback created
++ * for flexibility in adding new types of interface callbacks in future.
++ *
++ * @ipmi_intf: The IPMI interface number.
++ */
++static void ipmisensors_unregister_bmc(int ipmi_intf)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ if (cursor->interface_id == ipmi_intf) {
++ list_del(&cursor->list);
++ printk(KERN_DEBUG
++ "ipmisensors: cancelling queued work\n");
++ /* cancel update work queued for this bmc */
++ cancel_delayed_work(&cursor->update_work);
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev,
++ &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev,
++ &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ driver_data.interfaces--;
++ }
++ }
++
++}
++
++/**
++ * Unregister all registered bmcs.
++ */
++static void ipmisensors_unregister_bmc_all(void)
++{
++ struct ipmisensors_bmc_data *cursor, *next;
++
++ /* find and free the ipmisensors_bmc_data struct */
++ list_for_each_entry_safe(cursor, next, &driver_data.bmc_data, list) {
++ list_del(&cursor->list);
++
++ /* cancel update work queued for this bmc */
++ printk(KERN_DEBUG "ipmisensors: cancelling queued work\n");
++ cancel_delayed_work(&cursor->update_work);
++
++ printk(KERN_DEBUG
++ "ipmisensors: waiting for update to finish\n");
++ /* wait for readings to finish */
++ while (cursor->state != STATE_DONE) ;
++
++ device_remove_file(cursor->dev, &cursor->alarms_attr.dev_attr);
++ device_remove_file(cursor->dev, &cursor->update_attr.dev_attr);
++ hwmon_device_unregister(cursor->class_dev);
++ ipmisensors_sdr_cleanup(cursor);
++ ipmi_destroy_user(cursor->user);
++
++ printk(KERN_INFO
++ "ipmisensors: Unegistered IPMI interface %d\n",
++ cursor->interface_id);
++
++ kfree(cursor);
++ }
++
++ driver_data.interfaces = 0;
++}
++
++/**
++ * Callback for when a new IPMI SMI type interface is found.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_new_smi(int if_num, struct device *dev)
++{
++ struct ipmi_addr smi_address = {
++ IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
++ IPMI_BMC_CHANNEL,
++ {0},
++ };
++
++ /* calls the generic new interface function */
++ ipmisensors_register_bmc(if_num, &smi_address);
++}
++
++/**
++ * Callback for when an exisiting IPMI SMI type interface is gone.
++ *
++ * @if_num: The IPMI interface number.
++ */
++static void ipmisensors_smi_gone(int if_num)
++{
++ if (driver_data.interfaces > 0) {
++ ipmisensors_unregister_bmc(if_num);
++ }
++}
++
++/**
++ * Initialize the module.
++ */
++static int __init ipmisensors_init(void)
++{
++ int error;
++ printk(KERN_INFO "ipmisensors - IPMI BMC sensors interface\n");
++
++ /* init cache managers */
++ driver_data.sdrdata_cache =
++ kmem_cache_create("ipmisensors_sdrdata", sizeof(struct sdrdata), 0,
++ 0, NULL, NULL);
++ driver_data.sysfsattr_cache =
++ kmem_cache_create("ipmisensors_sysfsattr",
++ sizeof(struct ipmisensors_device_attribute), 0, 0,
++ NULL, NULL);
++
++ if (!driver_data.sdrdata_cache || !driver_data.sysfsattr_cache) {
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++ return -ENOMEM;
++ }
++
++ /* register IPMI interface callback(s) */
++ error = ipmi_smi_watcher_register(&driver_data.smi_watcher);
++ if (error) {
++ printk(KERN_WARNING
++ "ipmisensors: can't register smi watcher\n");
++ return error;
++ }
++
++ /* create work queue, keep it simple, single-threaded */
++ ipmisensors_workqueue =
++ create_singlethread_workqueue("ipmisensors_workqueue");
++
++ return 0;
++}
++
++/**
++ * Cleanup
++ */
++static void ipmisensors_cleanup(void)
++{
++ /* start cleanup */
++ cleanup = 1;
++
++ /* unregister bmcs */
++ printk(KERN_DEBUG "ipmisensors: unregister bmcs\n");
++ ipmi_smi_watcher_unregister(&driver_data.smi_watcher);
++ ipmisensors_unregister_bmc_all();
++
++ /* flush & destroy work queue */
++ printk(KERN_DEBUG "ipmisensors: destroy workqueue\n");
++ flush_workqueue(ipmisensors_workqueue);
++ destroy_workqueue(ipmisensors_workqueue);
++
++ /* remove cache managers */
++ if (driver_data.sdrdata_cache)
++ kmem_cache_destroy(driver_data.sdrdata_cache);
++ if (driver_data.sysfsattr_cache)
++ kmem_cache_destroy(driver_data.sysfsattr_cache);
++}
++
++/**
++ * Cleanup and exit the module
++ */
++static void __exit ipmisensors_exit(void)
++{
++ ipmisensors_cleanup();
++ printk(KERN_DEBUG "ipmisensors: cleanup finished\n");
++}
++
++MODULE_AUTHOR("Yani Ioannou <yani.ioannou@gmail.com>");
++MODULE_DESCRIPTION("IPMI BMC sensors");
++MODULE_LICENSE("GPL");
++
++module_init(ipmisensors_init);
++module_exit(ipmisensors_exit);
+diff -rduNp linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.h linux-2.6.22.1/drivers/hwmon/ipmisensors.h
+--- linux-2.6.22.1.oorig2/drivers/hwmon/ipmisensors.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/drivers/hwmon/ipmisensors.h 2007-07-24 14:22:26.000000000 +0200
+@@ -0,0 +1,240 @@
++/*
++ * ipmisensors.h - lm_sensors interface to IPMI sensors.
++ *
++ * Copyright (C) 2004-2006 Yani Ioannou <yani.ioannou@gmail.com>
++ *
++ * Adapted from bmcsensors (lm-sensors for linux 2.4)
++ * bmcsensors (C) Mark D. Studebaker <mdsxyz123@yahoo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This 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/ipmi.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/workqueue.h>
++
++/* SDR defs */
++#define STYPE_TEMP 0x01
++#define STYPE_VOLT 0x02
++#define STYPE_CURR 0x03
++#define STYPE_FAN 0x04
++
++#define SDR_LIMITS 8
++#define SDR_MAX_ID_LENGTH 16
++#define SDR_MAX_UNPACKED_ID_LENGTH ((SDR_MAX_ID_LENGTH * 4 / 3) + 2)
++
++/* the last sensor type we are interested in */
++#define STYPE_MAX 4
++
++#define IPMI_SDR_SIZE 67
++#define IPMI_CHUNK_SIZE 16
++
++#define MAX_FILENAME_LENGTH 30
++
++struct ipmisensors_device_attribute {
++ struct device_attribute dev_attr;
++ struct sdrdata *sdr;
++};
++#define to_ipmisensors_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_device_attribute, dev_attr)
++
++#define IPMISENSORS_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
++struct ipmisensors_attribute sensor_dev_attr_##_name = { \
++ .dev_attr = __ATTR(_name,_mode,_show,_store), \
++ .index = _index, \
++}
++
++struct ipmisensors_bmc_device_attribute {
++ struct device_attribute dev_attr;
++ struct ipmisensors_bmc_data *bmc;
++};
++#define to_ipmisensors_bmc_dev_attr(_dev_attr) \
++ container_of(_dev_attr, struct ipmisensors_bmc_device_attribute, dev_attr)
++
++/**
++ * &struct_sdrdata stores the IPMI Sensor Data Record (SDR) data, as recieved from the BMC, along with the corresponding sysfs attributes
++ */
++struct sdrdata {
++ struct list_head list;
++ /* retrieved from SDR, not expected to change */
++ /* Sensor Type Code */
++ u8 stype;
++ u8 number;
++ /* Sensor Capability Code */
++ u8 capab;
++ u16 thresh_mask;
++ u8 format;
++ u8 linear;
++ s16 m;
++ s16 b;
++ u8 k;
++ u8 nominal;
++ u8 limits[SDR_LIMITS];
++ /* index into limits for reported upper and lower limit */
++ int lim1, lim2;
++ u8 lim1_write, lim2_write;
++ u8 string_type;
++ u8 id_length;
++ u8 id[SDR_MAX_ID_LENGTH];
++ /* retrieved from reading */
++ u8 reading;
++ u8 status;
++ u8 thresholds;
++ /* sensor's bmc */
++ struct ipmisensors_bmc_data *bmc;
++ /* sysfs entries */
++ struct ipmisensors_device_attribute attr;
++ char *attr_name;
++ struct ipmisensors_device_attribute attr_min;
++ char *attr_min_name;
++ struct ipmisensors_device_attribute attr_max;
++ char *attr_max_name;
++ struct ipmisensors_device_attribute attr_label;
++ char *attr_label_name;
++
++};
++
++/**
++ * &struct_ipmisensors_data stores the data for the ipmisensors driver.
++ */
++struct ipmisensors_data {
++ /* Driver struct */
++ char *driver_name;
++
++ /* Linked list of ipmisensors_bmc_data structs, one for each BMC */
++ struct list_head bmc_data;
++
++ /* Number of ipmi interfaces (and hence ipmisensors_data structs). */
++ int interfaces;
++
++ /* IPMI kernel interface - SMI watcher */
++ struct ipmi_smi_watcher smi_watcher;
++
++ /* IPMI kernel interface - user handlers */
++ struct ipmi_user_hndl ipmi_hndlrs;
++
++ /* Cache manager for sdrdata cache */
++ struct kmem_cache *sdrdata_cache;
++
++ /* Cache manager for ipmi_sensor_device_attribute cache */
++ struct kmem_cache *sysfsattr_cache;
++};
++
++/**
++ * &states: enumeration of state codes for a bmc specific ipmisensors
++ */
++enum states {
++ STATE_INIT,
++ STATE_RESERVE,
++ STATE_SDR,
++ STATE_SDRPARTIAL,
++ STATE_READING,
++ STATE_UNCANCEL,
++ STATE_SYSTABLE,
++ STATE_DONE
++};
++
++/**
++ * &struct_ipmisensors_bmc_data stores the data for a particular IPMI BMC.
++ */
++struct ipmisensors_bmc_data {
++ struct list_head list;
++
++ /* The IPMI interface number */
++ int interface_id;
++
++ /* The IPMI address */
++ struct ipmi_addr address;
++
++ /* List of sdrdata structs (sdrs) recieved from the BMC */
++ struct list_head sdrs;
++
++ /* Count of the number of sdrs stored in the sdr list */
++ int sdr_count;
++
++ /* next message id */
++ int msgid;
++
++ /* The ipmi interface 'user' used to access this particular bmc */
++ ipmi_user_t user;
++
++ /* BMC IPMI Version (major) */
++ unsigned char ipmi_version_major;
++
++ /* BMC IPMI Version (minor) */
++ unsigned char ipmi_version_minor;
++
++ /* The size of the SDR request message */
++ int ipmi_sdr_partial_size;
++
++ /* transmit message buffer */
++ struct kernel_ipmi_msg tx_message;
++
++ /* ipmi transmited data buffer */
++ unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; /* why the +50 in bmcsensors? */
++
++ /* ipmi recieved data buffer */
++ unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH + 50];
++
++ /* current recieve buffer offset */
++ int rx_msg_data_offset;
++
++ /* The id of then next SDR record to read during update cycle */
++ u16 nextrecord;
++
++ /* BMC SDR Reservation ID */
++ u16 resid;
++
++ /* Alarm status */
++ u8 alarms;
++
++ /* The cumalative error count for this bmc */
++ int errorcount;
++
++ /* The current state of this bmc w.r.t. ipmisensors (see enum states) */
++ int state;
++
++ /* The current sdr for which a reading is pending */
++ struct sdrdata *current_sdr;
++
++ /* The BMC's device struct */
++ struct device *dev;
++
++ /* hwmon class device */
++ struct class_device *class_dev;
++
++ /* hwmon device name */
++ struct device_attribute name_attr;
++
++ /* alarms attribute */
++ struct ipmisensors_bmc_device_attribute alarms_attr;
++
++ /* update_period attribute */
++ struct ipmisensors_bmc_device_attribute update_attr;
++
++ /* lower bound on time between updates (in seconds) */
++ unsigned int update_period;
++
++ /* semaphore used to do a headcount of the SDR readings we are waiting
++ * on in a given bmc update */
++ struct semaphore update_semaphore;
++
++ /* bmc's work struct for updating sensors */
++ struct delayed_work update_work;
++
++ /* bmc's work struct for building the sysfs workqueue */
++ struct work_struct sysfs_work;
++};
+diff -rduNp linux-2.6.22.1.oorig2/include/linux/ipmi.h linux-2.6.22.1/include/linux/ipmi.h
+--- linux-2.6.22.1.oorig2/include/linux/ipmi.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/include/linux/ipmi.h 2007-07-24 14:22:26.000000000 +0200
+@@ -300,6 +300,9 @@ int ipmi_create_user(unsigned int
+ safe, too. */
+ int ipmi_destroy_user(ipmi_user_t user);
+
++/* Get the IPMI BMC's device struct */
++struct device *ipmi_get_bmcdevice(int ipmi_intf);
++
+ /* Get the IPMI version of the BMC we are talking to. */
+ void ipmi_get_version(ipmi_user_t user,
+ unsigned char *major,
+diff -rduNp linux-2.6.22.1.oorig2/include/linux/ipmi_msgdefs.h linux-2.6.22.1/include/linux/ipmi_msgdefs.h
+--- linux-2.6.22.1.oorig2/include/linux/ipmi_msgdefs.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/include/linux/ipmi_msgdefs.h 2007-07-24 14:22:26.000000000 +0200
+@@ -45,6 +45,7 @@
+
+ #define IPMI_NETFN_APP_REQUEST 0x06
+ #define IPMI_NETFN_APP_RESPONSE 0x07
++#define IPMI_GET_DEVICE_GUID_CMD 0x08
+ #define IPMI_GET_DEVICE_ID_CMD 0x01
+ #define IPMI_COLD_RESET_CMD 0x02
+ #define IPMI_WARM_RESET_CMD 0x03
+@@ -57,6 +58,11 @@
+ #define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
+ #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
+ #define IPMI_GET_CHANNEL_INFO_CMD 0x42
++#define IPMI_RESERVE_SDR 0x22
++#define IPMI_GET_SDR 0x23
++#define IPMI_GET_SENSOR_STATE_READING 0x2D
++#define IPMI_SET_SENSOR_HYSTERESIS 0x24
++#define IPMI_SET_SENSOR_THRESHOLD 0x26
+
+ #define IPMI_NETFN_STORAGE_REQUEST 0x0a
+ #define IPMI_NETFN_STORAGE_RESPONSE 0x0b
+@@ -79,10 +85,13 @@
+ #define IPMI_NODE_BUSY_ERR 0xc0
+ #define IPMI_INVALID_COMMAND_ERR 0xc1
+ #define IPMI_TIMEOUT_ERR 0xc3
++#define IPMI_INVALID_RESERVATION_ID 0xc5
+ #define IPMI_ERR_MSG_TRUNCATED 0xc6
+ #define IPMI_REQ_LEN_INVALID_ERR 0xc7
+ #define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
+ #define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
++#define IPMI_ERR_RETURNING_REQ_BYTES 0xca
++#define IPMI_ERR_PROVIDING_RESPONSE 0xce
+ #define IPMI_LOST_ARBITRATION_ERR 0x81
+ #define IPMI_BUS_ERR 0x82
+ #define IPMI_NAK_ON_WRITE_ERR 0x83
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-new.makefile b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-new.makefile
new file mode 100644
index 0000000000..7852c04bcc
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-new.makefile
@@ -0,0 +1,91 @@
+#############################################################
+#
+# full kernel tarballs >= 2.6.19.1
+#
+#############################################################
+
+# new-style kernels?
+ifeq ($(LINUX_HEADERS_VERSION),)
+# parse linux version string
+LNXVER:=$(subst ., , $(strip $(DEFAULT_KERNEL_HEADERS)))
+VERSION:=$(word 1, $(LNXVER))
+PATCHLEVEL:=$(word 2, $(LNXVER))
+SUBLEVEL:=$(word 3, $(LNXVER))
+EXTRAVERSION:=$(word 4, $(LNXVER))
+LOCALVERSION:=
+
+# should contain prepended dot
+EXTRAVERSION:=$(if $(EXTRAVERSION),.$(EXTRAVERSION),)
+
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=$(BR2_KERNEL_MIRROR)/linux/kernel/v2.6/
+LINUX_HEADERS_SOURCE:=linux-$(LINUX_HEADERS_VERSION).tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-$(LINUX_HEADERS_VERSION)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_IS_KERNEL=y
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.22.1")
+LINUX_RT_VERSION:=rt9
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.21.5")
+LINUX_RT_VERSION:=rt20
+endif
+
+ifeq ($(LINUX_HEADERS_IS_KERNEL),y)
+# Need to redefine KERNEL_HEADERS_PATCH_DIR if you want
+# board specific kernel headers
+KERNEL_HEADERS_PATCH_DIR:=toolchain/kernel-headers/empty
+LINUX_HEADERS_DEPENDS:=
+
+ifeq ($(BR2_KERNEL_HEADERS_RT),y)
+LINUX_RT_SOURCE:=patch-$(LINUX_HEADERS_VERSION)-$(LINUX_RT_VERSION)
+LINUX_RT_SITE:=$(BR2_KERNEL_MIRROR)/linux/kernel/projects/rt/older/
+LINUX_HEADERS_DEPENDS+=$(DL_DIR)/$(LINUX_RT_SOURCE)
+$(DL_DIR)/$(LINUX_RT_SOURCE):
+ $(WGET) -P $(DL_DIR) $(LINUX_RT_SITE)/$(LINUX_RT_SOURCE)
+endif
+
+$(LINUX_HEADERS_UNPACK_DIR)/.unpacked: $(DL_DIR)/$(LINUX_HEADERS_SOURCE)
+ @echo "*** Using kernel-headers generated from kernel source"
+ rm -rf $(LINUX_HEADERS_DIR)
+ [ -d $(TOOL_BUILD_DIR) ] || $(INSTALL) -d $(TOOL_BUILD_DIR)
+ $(LINUX_HEADERS_CAT) $(DL_DIR)/$(LINUX_HEADERS_SOURCE) | tar -C $(TOOL_BUILD_DIR) $(TAR_OPTIONS) -
+ touch $@
+
+$(LINUX_HEADERS_UNPACK_DIR)/.patched: $(LINUX_HEADERS_UNPACK_DIR)/.unpacked $(LINUX_HEADERS_DEPENDS)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) toolchain/kernel-headers \
+ linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2}
+ifeq ($(BR2_KERNEL_HEADERS_IPMI),y)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) toolchain/kernel-headers/ipmi \
+ linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2}
+endif
+ifeq ($(BR2_KERNEL_HEADERS_LZMA),y)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) toolchain/kernel-headers/lzma \
+ linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2}
+endif
+ifeq ($(BR2_KERNEL_HEADERS_RT),y)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) $(DL_DIR) $(LINUX_RT_SOURCE)
+endif
+ifeq ($(BR2_KERNEL_HEADERS_PATCH_DIR),y)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) $(KERNEL_HEADERS_PATCH_DIR) \
+ \*.patch{,.gz,.bz2}
+endif
+ifeq ($(BR2_PACKAGE_OPENSWAN),y)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) package/openswan \
+ linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2}
+endif
+ touch $@
+
+$(LINUX_HEADERS_DIR)/.configured: $(LINUX_HEADERS_UNPACK_DIR)/.patched
+ (cd $(LINUX_HEADERS_UNPACK_DIR); \
+ $(MAKE) ARCH=$(KERNEL_ARCH) \
+ HOSTCC="$(HOSTCC)" HOSTCFLAGS="$(HOSTCFLAGS)" \
+ HOSTCXX="$(HOSTCXX)" \
+ INSTALL_HDR_PATH=$(LINUX_HEADERS_DIR) headers_install; \
+ )
+ touch $@
+
+endif
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old-versions.makefile b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old-versions.makefile
new file mode 100644
index 0000000000..01e530084f
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old-versions.makefile
@@ -0,0 +1,103 @@
+#############################################################
+#
+# Setup the kernel headers. I include a generic package of
+# kernel headers here, so you shouldn't need to include your
+# own. Be aware these kernel headers _will_ get blown away
+# by a 'make clean' so don't put anything sacred in here...
+#
+#############################################################
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.4.25")
+VERSION:=2
+PATCHLEVEL:=4
+SUBLEVEL:=25
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://www.uclibc.org/downloads/toolchain
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.4.25.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.4.25
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.4.27")
+VERSION:=2
+PATCHLEVEL:=4
+SUBLEVEL:=27
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://www.uclibc.org/downloads/toolchain
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.4.27.tar.bz2
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.4.27
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.4.29")
+VERSION:=2
+PATCHLEVEL:=4
+SUBLEVEL:=29
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://www.uclibc.org/downloads/toolchain
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.4.29.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.4.29
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.4.31")
+VERSION:=2
+PATCHLEVEL:=4
+SUBLEVEL:=31
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://www.uclibc.org/downloads/toolchain
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.4.31.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.4.31
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.9")
+VERSION:=2
+PATCHLEVEL:=6
+SUBLEVEL:=9
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.6.9.1.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.6.9.1
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.10")
+VERSION:=2
+PATCHLEVEL:=6
+SUBLEVEL:=10
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.6.10.0.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.6.10.0
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.11")
+VERSION:=2
+PATCHLEVEL:=6
+SUBLEVEL:=11
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.6.11.0.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.6.11.0
+endif
+
+ifeq ("$(DEFAULT_KERNEL_HEADERS)","2.6.12")
+VERSION:=2
+PATCHLEVEL:=6
+SUBLEVEL:=12
+LINUX_HEADERS_VERSION:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+LINUX_HEADERS_SITE:=http://ep09.pld-linux.org/~mmazur/linux-libc-headers/
+LINUX_HEADERS_SOURCE:=linux-libc-headers-2.6.12.0.tar.bz2
+LINUX_HEADERS_CAT:=$(BZCAT)
+LINUX_HEADERS_DIR:=$(TOOL_BUILD_DIR)/linux
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-2.6.12.0
+endif
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old.makefile b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old.makefile
new file mode 100644
index 0000000000..52fa68e6f3
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers-old.makefile
@@ -0,0 +1,87 @@
+#############################################################
+#
+# Setup the kernel headers. I include a generic package of
+# kernel headers here, so you shouldn't need to include your
+# own. Be aware these kernel headers _will_ get blown away
+# by a 'make clean' so don't put anything sacred in here...
+#
+#############################################################
+
+# the old sanitized kernel-headers
+ifeq ($(LINUX_HEADERS_IS_KERNEL),n)
+
+$(LINUX_HEADERS_UNPACK_DIR)/.unpacked: $(DL_DIR)/$(LINUX_HEADERS_SOURCE)
+ @echo "Using old sanitized kernel-headers"
+ rm -rf $(LINUX_HEADERS_DIR)
+ $(LINUX_HEADERS_CAT) $(DL_DIR)/$(LINUX_HEADERS_SOURCE) | tar -C $(TOOL_BUILD_DIR) $(TAR_OPTIONS) -
+ifneq ($(LINUX_HEADERS_UNPACK_DIR),$(LINUX_HEADERS_DIR))
+ ln -fs $(LINUX_HEADERS_UNPACK_DIR) $(LINUX_HEADERS_DIR)
+endif
+ touch $(LINUX_HEADERS_UNPACK_DIR)/.unpacked
+
+$(LINUX_HEADERS_DIR)/.patched: $(LINUX_HEADERS_UNPACK_DIR)/.unpacked
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_DIR) toolchain/kernel-headers \
+ linux-libc-headers-$(LINUX_HEADERS_VERSION)\*.patch
+ifeq ($(strip $(ARCH)),nios2)
+ toolchain/patch-kernel.sh $(LINUX_HEADERS_DIR) toolchain/kernel-headers \
+ linux-libc-headers-$(LINUX_HEADERS_VERSION)-nios2nommu.patch.conditional
+endif
+ touch $(LINUX_HEADERS_DIR)/.patched
+
+$(LINUX_HEADERS_DIR)/.configured: $(LINUX_HEADERS_DIR)/.patched
+ rm -f $(LINUX_HEADERS_DIR)/include/asm
+ @if [ ! -f $(LINUX_HEADERS_DIR)/Makefile ] ; then \
+ /bin/echo -e "VERSION = $(VERSION)\nPATCHLEVEL = $(PATCHLEVEL)\n" > \
+ $(LINUX_HEADERS_DIR)/Makefile; \
+ /bin/echo -e "SUBLEVEL = $(SUBLEVEL)\nEXTRAVERSION =\n" >> \
+ $(LINUX_HEADERS_DIR)/Makefile; \
+ /bin/echo -e "KERNELRELEASE=\$$(VERSION).\$$(PATCHLEVEL).\$$(SUBLEVEL)\$$(EXTRAVERSION)" >> \
+ $(LINUX_HEADERS_DIR)/Makefile; \
+ fi
+ @if [ "$(ARCH)" = "powerpc" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-ppc$(NOMMU) asm;) \
+ elif [ "$(ARCH)" = "mips" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-mips$(NOMMU) asm;) \
+ elif [ "$(ARCH)" = "mipsel" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-mips$(NOMMU) asm;) \
+ elif [ "$(ARCH)" = "nios2" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-nios2nommu asm;) \
+ elif [ "$(ARCH)" = "arm" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-arm$(NOMMU) asm; \
+ cd asm; \
+ if [ ! -L proc ] ; then \
+ ln -fs proc-armv proc; \
+ ln -fs arch-ebsa285 arch; fi); \
+ elif [ "$(ARCH)" = "armeb" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-arm$(NOMMU) asm; \
+ cd asm; \
+ if [ ! -L proc ] ; then \
+ ln -fs proc-armv proc; \
+ ln -fs arch-ebsa285 arch; fi); \
+ elif [ "$(ARCH)" = "cris" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-cris asm;) \
+ elif [ "$(ARCH)" = "sh3" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-sh asm; \
+ cd asm; \
+ ln -s cpu-sh3 cpu) \
+ elif [ "$(ARCH)" = "sh3eb" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-sh asm; \
+ cd asm; \
+ ln -s cpu-sh3 cpu) \
+ elif [ "$(ARCH)" = "sh4" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-sh asm; \
+ cd asm; \
+ ln -s cpu-sh4 cpu) \
+ elif [ "$(ARCH)" = "sh4eb" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-sh asm; \
+ cd asm; \
+ ln -s cpu-sh4 cpu) \
+ elif [ "$(ARCH)" = "i386" -o "$(ARCH)" = "i486" -o "$(ARCH)" = "i586" -o "$(ARCH)" = "i686" ];then \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-i386$(NOMMU) asm;) \
+ else \
+ (cd $(LINUX_HEADERS_DIR)/include; ln -fs asm-$(ARCH)$(NOMMU) asm;) \
+ fi
+ touch $(LINUX_HEADERS_DIR)/include/linux/autoconf.h
+ touch $(LINUX_HEADERS_DIR)/.configured
+
+endif
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers.mk b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers.mk
new file mode 100644
index 0000000000..fc8acda051
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/kernel-headers.mk
@@ -0,0 +1,48 @@
+#############################################################
+#
+# Setup the kernel headers. I include a generic package of
+# kernel headers here, so you shouldn't need to include your
+# own. Be aware these kernel headers _will_ get blown away
+# by a 'make clean' so don't put anything sacred in here...
+#
+#############################################################
+
+DEFAULT_KERNEL_HEADERS:=$(strip $(subst ",, $(BR2_DEFAULT_KERNEL_HEADERS)))
+#"))
+
+LINUX_HEADERS_SITE:=127.0.0.1
+LINUX_HEADERS_SOURCE:=unspecified-kernel-headers
+LINUX_HEADERS_UNPACK_DIR:=$(TOOL_BUILD_DIR)/linux-libc-headers-null
+
+KERNEL_ARCH:=$(shell $(SHELL) -c "echo \"$(ARCH)\" | sed -e \"s/-.*//\" \
+ -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/powerpc64/powerpc/ \
+ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+ -e s/sh2.*/sh/ -e s/sh3.*/sh/ -e s/sh4.*/sh/ \
+ -e s/nios2.*/nios2nommu/")
+
+# assume old manually sanitized kernel-headers
+LINUX_HEADERS_IS_KERNEL=n
+
+# this needs to be included before kernel-headers-new to set old-style mode
+include toolchain/kernel-headers/kernel-headers-old-versions.makefile
+include toolchain/kernel-headers/kernel-headers-new.makefile
+include toolchain/kernel-headers/kernel-headers-old.makefile
+
+$(DL_DIR)/$(LINUX_HEADERS_SOURCE):
+ $(WGET) -P $(DL_DIR) $(LINUX_HEADERS_SITE)/$(LINUX_HEADERS_SOURCE)
+
+kernel-headers: $(LINUX_HEADERS_DIR)/.configured
+
+kernel-headers-source: $(DL_DIR)/$(LINUX_HEADERS_SOURCE)
+
+kernel-headers-clean: clean
+ rm -rf $(LINUX_HEADERS_DIR)
+
+kernel-headers-dirclean:
+ rm -rf $(LINUX_HEADERS_DIR)
+ rm -rf $(LINUX_HEADERS_UNPACK_DIR)
+
+.PHONY: kernel-headers
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.20.4-dwmw2-combined.01.diff b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.20.4-dwmw2-combined.01.diff
new file mode 100644
index 0000000000..d07dd33d2b
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.20.4-dwmw2-combined.01.diff
@@ -0,0 +1,460 @@
+\\\\ dwmw2's --combine -fwhole-program patch for the kernel
+\\ original of this incarnation was here:
+\\ http://david.woodhou.se/linux-combine-build.patch
+diff -rduNp linux-2.6.20.4.orig/drivers/md/md.c linux-2.6.20.4/drivers/md/md.c
+--- linux-2.6.20.4.orig/drivers/md/md.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/drivers/md/md.c 2007-03-24 20:14:10.000000000 +0100
+@@ -2944,6 +2944,7 @@ static struct kobj_type md_ktype = {
+ };
+
+ int mdp_major = 0;
++__internal_export(mdp_major);
+
+ static struct kobject *md_probe(dev_t dev, int *part, void *data)
+ {
+@@ -5602,7 +5603,7 @@ void md_autodetect_dev(dev_t dev)
+ if (dev_cnt >= 0 && dev_cnt < 127)
+ detected_devices[dev_cnt++] = dev;
+ }
+-
++__internal_export(md_autodetect_dev);
+
+ static void autostart_arrays(int part)
+ {
+diff -rduNp linux-2.6.20.4.orig/drivers/video/fbcvt.c linux-2.6.20.4/drivers/video/fbcvt.c
+--- linux-2.6.20.4.orig/drivers/video/fbcvt.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/drivers/video/fbcvt.c 2007-03-24 20:14:10.000000000 +0100
+@@ -376,3 +376,4 @@ int fb_find_mode_cvt(struct fb_videomode
+
+ return 0;
+ }
++__internal_export(fb_find_mode_cvt);
+diff -rduNp linux-2.6.20.4.orig/fs/debugfs/inode.c linux-2.6.20.4/fs/debugfs/inode.c
+--- linux-2.6.20.4.orig/fs/debugfs/inode.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/debugfs/inode.c 2007-03-24 20:14:10.000000000 +0100
+@@ -29,7 +29,7 @@
+ #define DEBUGFS_MAGIC 0x64626720
+
+ /* declared over in file.c */
+-extern struct file_operations debugfs_file_operations;
++extern const struct file_operations debugfs_file_operations;
+
+ static struct vfsmount *debugfs_mount;
+ static int debugfs_mount_count;
+diff -rduNp linux-2.6.20.4.orig/fs/devpts/inode.c linux-2.6.20.4/fs/devpts/inode.c
+--- linux-2.6.20.4.orig/fs/devpts/inode.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/devpts/inode.c 2007-03-24 20:14:10.000000000 +0100
+@@ -185,6 +185,7 @@ int devpts_pty_new(struct tty_struct *tt
+
+ return 0;
+ }
++__internal_export(devpts_pty_new);
+
+ struct tty_struct *devpts_get_tty(int number)
+ {
+@@ -202,6 +203,7 @@ struct tty_struct *devpts_get_tty(int nu
+
+ return tty;
+ }
++__internal_export(devpts_get_tty);
+
+ void devpts_pty_kill(int number)
+ {
+@@ -218,6 +220,7 @@ void devpts_pty_kill(int number)
+ }
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
+ }
++__internal_export(devpts_pty_kill);
+
+ static int __init init_devpts_fs(void)
+ {
+diff -rduNp linux-2.6.20.4.orig/fs/hfsplus/inode.c linux-2.6.20.4/fs/hfsplus/inode.c
+--- linux-2.6.20.4.orig/fs/hfsplus/inode.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/hfsplus/inode.c 2007-03-24 20:14:10.000000000 +0100
+@@ -269,7 +269,7 @@ static int hfsplus_file_release(struct i
+ }
+
+ extern struct inode_operations hfsplus_dir_inode_operations;
+-extern struct file_operations hfsplus_dir_operations;
++extern const struct file_operations hfsplus_dir_operations;
+
+ static struct inode_operations hfsplus_file_inode_operations = {
+ .lookup = hfsplus_file_lookup,
+diff -rduNp linux-2.6.20.4.orig/fs/hugetlbfs/inode.c linux-2.6.20.4/fs/hugetlbfs/inode.c
+--- linux-2.6.20.4.orig/fs/hugetlbfs/inode.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/hugetlbfs/inode.c 2007-03-24 20:14:10.000000000 +0100
+@@ -45,6 +45,7 @@ static struct backing_dev_info hugetlbfs
+ };
+
+ int sysctl_hugetlb_shm_group;
++__internal_export(sysctl_hugetlb_shm_group);
+
+ static void huge_pagevec_release(struct pagevec *pvec)
+ {
+@@ -562,6 +563,7 @@ const struct file_operations hugetlbfs_f
+ .fsync = simple_sync_file,
+ .get_unmapped_area = hugetlb_get_unmapped_area,
+ };
++__internal_export(hugetlbfs_file_operations);
+
+ static struct inode_operations hugetlbfs_dir_inode_operations = {
+ .create = hugetlbfs_create,
+@@ -701,6 +703,7 @@ int hugetlb_get_quota(struct address_spa
+
+ return ret;
+ }
++__internal_export(hugetlb_get_quota);
+
+ void hugetlb_put_quota(struct address_space *mapping)
+ {
+@@ -712,6 +715,7 @@ void hugetlb_put_quota(struct address_sp
+ spin_unlock(&sbinfo->stat_lock);
+ }
+ }
++__internal_export(hugetlb_put_quota);
+
+ static int hugetlbfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+@@ -794,6 +798,7 @@ out_shm_unlock:
+ user_shm_unlock(size, current->user);
+ return ERR_PTR(error);
+ }
++__internal_export(hugetlb_zero_setup);
+
+ static int __init init_hugetlbfs_fs(void)
+ {
+diff -rduNp linux-2.6.20.4.orig/fs/proc/base.c linux-2.6.20.4/fs/proc/base.c
+--- linux-2.6.20.4.orig/fs/proc/base.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/proc/base.c 2007-03-24 20:18:09.000000000 +0100
+@@ -71,6 +71,7 @@
+ #include <linux/cpuset.h>
+ #include <linux/audit.h>
+ #include <linux/poll.h>
++#include <linux/module.h>
+ #include <linux/nsproxy.h>
+ #include <linux/oom.h>
+ #include "internal.h"
+@@ -2030,6 +2031,7 @@ struct dentry *proc_pid_lookup(struct in
+ out:
+ return result;
+ }
++__internal_export(proc_flush_task);
+
+ /*
+ * Find the first task with tgid >= tgid
+diff -rduNp linux-2.6.20.4.orig/fs/proc/generic.c linux-2.6.20.4/fs/proc/generic.c
+--- linux-2.6.20.4.orig/fs/proc/generic.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/proc/generic.c 2007-03-24 20:14:10.000000000 +0100
+@@ -20,8 +20,8 @@
+ #include <linux/namei.h>
+ #include <linux/bitops.h>
+ #include <linux/spinlock.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+-
+ #include "internal.h"
+
+ static ssize_t proc_file_read(struct file *file, char __user *buf,
+@@ -38,6 +38,7 @@ int proc_match(int len, const char *name
+ return 0;
+ return !memcmp(name, de->name, len);
+ }
++__internal_export(proc_match);
+
+ static struct file_operations proc_file_operations = {
+ .llseek = proc_file_lseek,
+diff -rduNp linux-2.6.20.4.orig/fs/proc/kcore.c linux-2.6.20.4/fs/proc/kcore.c
+--- linux-2.6.20.4.orig/fs/proc/kcore.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/proc/kcore.c 2007-03-24 20:14:10.000000000 +0100
+@@ -19,6 +19,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/highmem.h>
+ #include <linux/init.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+
+@@ -66,6 +67,7 @@ kclist_add(struct kcore_list *new, void
+ kclist = new;
+ write_unlock(&kclist_lock);
+ }
++__internal_export(kclist_add);
+
+ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
+ {
+diff -rduNp linux-2.6.20.4.orig/fs/proc/proc_tty.c linux-2.6.20.4/fs/proc/proc_tty.c
+--- linux-2.6.20.4.orig/fs/proc/proc_tty.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/proc/proc_tty.c 2007-03-24 20:14:10.000000000 +0100
+@@ -201,6 +201,7 @@ void proc_tty_register_driver(struct tty
+
+ driver->proc_entry = ent;
+ }
++__internal_export(proc_tty_register_driver);
+
+ /*
+ * This function is called by tty_unregister_driver()
+@@ -217,6 +218,7 @@ void proc_tty_unregister_driver(struct t
+
+ driver->proc_entry = NULL;
+ }
++__internal_export(proc_tty_unregister_driver);
+
+ /*
+ * Called by proc_root_init() to initialize the /proc/tty subtree
+diff -rduNp linux-2.6.20.4.orig/fs/proc/root.c linux-2.6.20.4/fs/proc/root.c
+--- linux-2.6.20.4.orig/fs/proc/root.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/proc/root.c 2007-03-24 20:14:10.000000000 +0100
+@@ -21,7 +21,9 @@
+
+ #include "internal.h"
+
+-struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
++struct proc_dir_entry *proc_net;
++
++struct proc_dir_entry *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
+
+ #ifdef CONFIG_SYSCTL
+ struct proc_dir_entry *proc_sys_root;
+@@ -91,6 +93,7 @@ void __init proc_root_init(void)
+ #endif
+ proc_bus = proc_mkdir("bus", NULL);
+ }
++__internal_export(proc_root_init);
+
+ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
+ )
+@@ -163,6 +166,7 @@ struct proc_dir_entry proc_root = {
+ .parent = &proc_root,
+ };
+
++__internal_export(proc_sys_root);
+ EXPORT_SYMBOL(proc_symlink);
+ EXPORT_SYMBOL(proc_mkdir);
+ EXPORT_SYMBOL(create_proc_entry);
+diff -rduNp linux-2.6.20.4.orig/fs/ramfs/inode.c linux-2.6.20.4/fs/ramfs/inode.c
+--- linux-2.6.20.4.orig/fs/ramfs/inode.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/ramfs/inode.c 2007-03-24 20:14:10.000000000 +0100
+@@ -225,5 +225,6 @@ int __init init_rootfs(void)
+ {
+ return register_filesystem(&rootfs_fs_type);
+ }
++__internal_export(init_rootfs);
+
+ MODULE_LICENSE("GPL");
+diff -rduNp linux-2.6.20.4.orig/fs/reiserfs/dir.c linux-2.6.20.4/fs/reiserfs/dir.c
+--- linux-2.6.20.4.orig/fs/reiserfs/dir.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/fs/reiserfs/dir.c 2007-03-24 20:14:10.000000000 +0100
+@@ -11,7 +11,7 @@
+ #include <linux/buffer_head.h>
+ #include <asm/uaccess.h>
+
+-extern struct reiserfs_key MIN_KEY;
++extern const struct reiserfs_key MIN_KEY;
+
+ static int reiserfs_readdir(struct file *, void *, filldir_t);
+ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
+diff -rduNp linux-2.6.20.4.orig/include/linux/module.h linux-2.6.20.4/include/linux/module.h
+--- linux-2.6.20.4.orig/include/linux/module.h 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/include/linux/module.h 2007-03-24 20:14:10.000000000 +0100
+@@ -20,6 +20,15 @@
+
+ #include <asm/module.h>
+
++
++#ifdef CONFIG_COMBINED_COMPILE
++#define __externally_visible__ __attribute__((externally_visible,used))
++#define __internal_export(sym) extern typeof(sym) sym __externally_visible__
++#else
++#define __externally_visible__
++#define __internal_export(sym)
++#endif
++
+ /* Not Yet Implemented */
+ #define MODULE_SUPPORTED_DEVICE(name)
+
+@@ -188,7 +197,7 @@ void *__symbol_get_gpl(const char *symbo
+
+ /* For every exported symbol, place a struct in the __ksymtab section */
+ #define __EXPORT_SYMBOL(sym, sec) \
+- extern typeof(sym) sym; \
++ extern typeof(sym) sym __externally_visible__; \
+ __CRC_SYMBOL(sym, sec) \
+ static const char __kstrtab_##sym[] \
+ __attribute__((section("__ksymtab_strings"))) \
+@@ -212,8 +221,8 @@ void *__symbol_get_gpl(const char *symbo
+ #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused")
+ #define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl")
+ #else
+-#define EXPORT_UNUSED_SYMBOL(sym)
+-#define EXPORT_UNUSED_SYMBOL_GPL(sym)
++#define EXPORT_UNUSED_SYMBOL(sym) __internal_export(sym)
++#define EXPORT_UNUSED_SYMBOL_GPL(sym) __internal_export(sym)
+ #endif
+
+ #endif
+@@ -471,11 +480,12 @@ void module_add_driver(struct module *,
+ void module_remove_driver(struct device_driver *);
+
+ #else /* !CONFIG_MODULES... */
+-#define EXPORT_SYMBOL(sym)
+-#define EXPORT_SYMBOL_GPL(sym)
+-#define EXPORT_SYMBOL_GPL_FUTURE(sym)
+-#define EXPORT_UNUSED_SYMBOL(sym)
+-#define EXPORT_UNUSED_SYMBOL_GPL(sym)
++
++#define EXPORT_SYMBOL(sym) __internal_export(sym)
++#define EXPORT_SYMBOL_GPL(sym) __internal_export(sym)
++#define EXPORT_SYMBOL_GPL_FUTURE(sym) __internal_export(sym)
++#define EXPORT_UNUSED_SYMBOL(sym) __internal_export(sym)
++#define EXPORT_UNUSED_SYMBOL_GPL(sym) __internal_export(sym)
+
+ /* Given an address, look for it in the exception tables. */
+ static inline const struct exception_table_entry *
+diff -rduNp linux-2.6.20.4.orig/init/do_mounts.c linux-2.6.20.4/init/do_mounts.c
+--- linux-2.6.20.4.orig/init/do_mounts.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/init/do_mounts.c 2007-03-24 20:14:10.000000000 +0100
+@@ -26,6 +26,10 @@ static char __initdata saved_root_name[6
+
+ dev_t ROOT_DEV;
+
++__internal_export(root_mountflags);
++__internal_export(rd_doload);
++__internal_export(ROOT_DEV);
++
+ static int __init load_ramdisk(char *str)
+ {
+ rd_doload = simple_strtol(str,NULL,0) & 3;
+@@ -205,6 +209,7 @@ fail:
+ res = 0;
+ goto done;
+ }
++__internal_export(name_to_dev_t);
+
+ static int __init root_dev_setup(char *line)
+ {
+@@ -446,4 +451,4 @@ out:
+ sys_chroot(".");
+ security_sb_post_mountroot();
+ }
+-
++__internal_export(prepare_namespace);
+diff -rduNp linux-2.6.20.4.orig/init/do_mounts_initrd.c linux-2.6.20.4/init/do_mounts_initrd.c
+--- linux-2.6.20.4.orig/init/do_mounts_initrd.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/init/do_mounts_initrd.c 2007-03-24 20:18:32.000000000 +0100
+@@ -6,6 +6,7 @@
+ #include <linux/romfs_fs.h>
+ #include <linux/initrd.h>
+ #include <linux/sched.h>
++#include <linux/module.h>
+ #include <linux/freezer.h>
+
+ #include "do_mounts.h"
+@@ -16,6 +17,11 @@ unsigned int real_root_dev; /* do_proc_d
+ static int __initdata old_fd, root_fd;
+ static int __initdata mount_initrd = 1;
+
++__internal_export(initrd_start);
++__internal_export(initrd_end);
++__internal_export(initrd_below_start_ok);
++__internal_export(real_root_dev);
++
+ static int __init no_initrd(char *str)
+ {
+ mount_initrd = 0;
+diff -rduNp linux-2.6.20.4.orig/init/do_mounts_rd.c linux-2.6.20.4/init/do_mounts_rd.c
+--- linux-2.6.20.4.orig/init/do_mounts_rd.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/init/do_mounts_rd.c 2007-03-24 20:14:10.000000000 +0100
+@@ -7,12 +7,14 @@
+ #include <linux/cramfs_fs.h>
+ #include <linux/initrd.h>
+ #include <linux/string.h>
++#include <linux/module.h>
+
+ #include "do_mounts.h"
+
+ #define BUILD_CRAMDISK
+
+ int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
++__internal_export(rd_prompt);
+
+ static int __init prompt_ramdisk(char *str)
+ {
+@@ -22,6 +24,7 @@ static int __init prompt_ramdisk(char *s
+ __setup("prompt_ramdisk=", prompt_ramdisk);
+
+ int __initdata rd_image_start; /* starting block # of image */
++__internal_export(rd_image_start);
+
+ static int __init ramdisk_start_setup(char *str)
+ {
+diff -rduNp linux-2.6.20.4.orig/init/Kconfig linux-2.6.20.4/init/Kconfig
+--- linux-2.6.20.4.orig/init/Kconfig 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/init/Kconfig 2007-03-24 20:14:10.000000000 +0100
+@@ -526,6 +526,11 @@ config MODULE_FORCE_UNLOAD
+ rmmod). This is mainly for kernel developers and desperate users.
+ If unsure, say N.
+
++config COMBINED_COMPILE
++ bool "Use combined compilation (gcc --combine)"
++ help
++ fish
++
+ config MODVERSIONS
+ bool "Module versioning support"
+ depends on MODULES
+diff -rduNp linux-2.6.20.4.orig/net/netfilter/core.c linux-2.6.20.4/net/netfilter/core.c
+--- linux-2.6.20.4.orig/net/netfilter/core.c 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/net/netfilter/core.c 2007-03-24 20:14:10.000000000 +0100
+@@ -279,3 +279,5 @@ void __init netfilter_init(void)
+ if (netfilter_log_init() < 0)
+ panic("cannot initialize nf_log");
+ }
++__internal_export(netfilter_init);
++
+diff -rduNp linux-2.6.20.4.orig/scripts/Makefile.build linux-2.6.20.4/scripts/Makefile.build
+--- linux-2.6.20.4.orig/scripts/Makefile.build 2007-03-13 19:27:08.000000000 +0100
++++ linux-2.6.20.4/scripts/Makefile.build 2007-03-24 20:14:10.000000000 +0100
+@@ -128,6 +128,11 @@ $(multi-objs-y:.o=.i) : modname = $(mo
+ $(multi-objs-y:.o=.s) : modname = $(modname-multi)
+ $(multi-objs-y:.o=.lst) : modname = $(modname-multi)
+
++ifdef CONFIG_COMBINED_COMPILE
++$(multi-used-m) : CFLAGS += -fwhole-program --combine $(sort $(addprefix $(srctree)/$(obj)/,$($(subst $(obj)/,,$(@:.o=-y)):.o=.c) $($(subst $(obj)/,,$(@:.o=-objs)):.o=.c)))
++$(multi-used-y) : CFLAGS += -fwhole-program --combine $(sort $(addprefix $(srctree)/$(obj)/,$($(subst $(obj)/,,$(@:.o=-y)):.o=.c) $($(subst $(obj)/,,$(@:.o=-objs)):.o=.c)))
++endif
++
+ quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
+ cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
+
+@@ -284,6 +289,22 @@ $(lib-target): $(lib-y) FORCE
+ targets += $(lib-target)
+ endif
+
++ifdef CONFIG_COMBINED_COMPILE
++# We would rather have a list of rules like
++# foo.o: $(foo-objs)
++# but that's not so easy, so we rather make all composite objects depend
++# on the set of all their parts
++
++$(multi-used-y) : %.o: $(srctree)/dummy.c $(multi-objs-y:.o=.c) FORCE
++ $(call cmd,force_checksrc)
++ $(call if_changed_rule,cc_o_c)
++
++$(multi-used-m) : %.o: $(srctree)/dummy.c $(multi-objs-m:.o=.c) FORCE
++ $(call cmd,force_checksrc)
++ $(call if_changed_rule,cc_o_c)
++
++targets += $(multi-used-y) $(multi-used-m)
++else
+ #
+ # Rule to link composite objects
+ #
+@@ -314,7 +335,7 @@ $(multi-used-m) : %.o: $(multi-objs-m) F
+ @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
+
+ targets += $(multi-used-y) $(multi-used-m)
+-
++endif
+
+ # Descending
+ # ---------------------------------------------------------------------------
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-001-add-linkage-header.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-001-add-linkage-header.patch
new file mode 100644
index 0000000000..dd89d4a893
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-001-add-linkage-header.patch
@@ -0,0 +1,18 @@
+diff -ur linux-2.6.21.5/include/asm-arm/Kbuild linux-2.6.21.5-patched/include/asm-arm/Kbuild
+--- linux-2.6.21.5/include/asm-arm/Kbuild 2007-06-11 13:37:06.000000000 -0500
++++ linux-2.6.21.5-patched/include/asm-arm/Kbuild 2008-02-27 18:17:46.999128276 -0600
+@@ -1 +1,3 @@
+ include include/asm-generic/Kbuild.asm
++
++header-y += linkage.h
+diff -ur linux-2.6.21.5/include/linux/Kbuild linux-2.6.21.5-patched/include/linux/Kbuild
+--- linux-2.6.21.5/include/linux/Kbuild 2007-06-11 13:37:06.000000000 -0500
++++ linux-2.6.21.5-patched/include/linux/Kbuild 2008-02-27 18:15:05.921149678 -0600
+@@ -100,6 +100,7 @@
+ header-y += jffs2.h
+ header-y += keyctl.h
+ header-y += limits.h
++header-y += linkage.h
+ header-y += lock_dlm_plock.h
+ header-y += magic.h
+ header-y += major.h
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-006-wait-for-async-scanned-block-devices.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-006-wait-for-async-scanned-block-devices.patch
new file mode 100644
index 0000000000..910b43ad9b
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.21.5-006-wait-for-async-scanned-block-devices.patch
@@ -0,0 +1,55 @@
+diff --git a/init/do_mounts.c b/init/do_mounts.c
+index 46fe407..efc134c 100644
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -25,6 +25,7 @@ int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */
+ int root_mountflags = MS_RDONLY | MS_SILENT;
+ char * __initdata root_device_name;
+ static char __initdata saved_root_name[64];
++int __initdata root_wait;
+
+ dev_t ROOT_DEV;
+
+@@ -216,6 +217,14 @@ static int __init root_dev_setup(char *line)
+
+ __setup("root=", root_dev_setup);
+
++static int __init rootwait_setup(char *line)
++{
++ root_wait = simple_strtol(line,NULL,0);
++ return 1;
++}
++
++__setup("rootwait=", rootwait_setup);
++
+ static char * __initdata root_mount_data;
+ static int __init root_data_setup(char *str)
+ {
+@@ -438,11 +447,24 @@ void __init prepare_namespace(void)
+ root_device_name += 5;
+ }
+
+- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+-
+ if (initrd_load())
+ goto out;
+
++ /* wait for any asynchronous scanning to complete */
++ if ((ROOT_DEV == 0) && root_wait) {
++ printk(KERN_INFO "Waiting for root device %s...\n",
++ saved_root_name);
++ do {
++ while (driver_probe_done() != 0)
++ msleep(100);
++ ROOT_DEV = name_to_dev_t(saved_root_name);
++ if (ROOT_DEV == 0)
++ msleep(100);
++ } while (ROOT_DEV == 0);
++ }
++
++ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
++
+ if (is_floppy && rd_doload && rd_load_disk(0))
+ ROOT_DEV = Root_RAM0;
+
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.23-nios2nommu.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.23-nios2nommu.patch
new file mode 100644
index 0000000000..6e558fd66c
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.23-nios2nommu.patch
@@ -0,0 +1,26567 @@
+diff --git a/arch/nios2nommu/ChangeLog b/arch/nios2nommu/ChangeLog
+new file mode 100644
+index 0000000..039c010
+--- /dev/null
++++ b/arch/nios2nommu/ChangeLog
+@@ -0,0 +1,4 @@
++2004-06-15 Ken Hill <khill@microtronix.com>
++
++ * Kconfig: Add Microtronix uKit support.
++
+diff --git a/arch/nios2nommu/Kconfig b/arch/nios2nommu/Kconfig
+new file mode 100644
+index 0000000..525c77b
+--- /dev/null
++++ b/arch/nios2nommu/Kconfig
+@@ -0,0 +1,403 @@
++#
++# For a description of the syntax of this configuration file,
++# see the Configure script.
++#
++mainmenu 'uClinux/Nios2 (w/o MMU) Kernel Configuration'
++
++config MMU
++ bool
++ default n
++
++config FPU
++ bool
++ default n
++
++config ZONE_DMA
++ bool
++ default y
++
++config UID16
++ bool
++ default y
++
++config RWSEM_GENERIC_SPINLOCK
++ bool
++ default y
++
++config RWSEM_XCHGADD_ALGORITHM
++ bool
++ default n
++
++config GENERIC_FIND_NEXT_BIT
++ bool
++ default y
++
++config GENERIC_HWEIGHT
++ bool
++ default y
++
++config GENERIC_CALIBRATE_DELAY
++ bool
++ default y
++
++source "init/Kconfig"
++
++menu "Processor type and features"
++
++comment 'Platform dependant setup'
++
++choice
++ prompt "CPU"
++ default NIOS2
++
++config NIOS2
++ bool "NIOS2"
++ help
++ Altera Nios2 softcore processor.
++
++endchoice
++
++choice
++ prompt "Platform"
++ default ALTERA_STRATIX
++
++config MICROTRONIX_UKIT
++ bool "Microtronix uKit board support"
++ depends on NIOS2
++ help
++ Support for the Microtronix uKit development board. Includes support
++ for Sodimm SDRAM/FLASH, soft ethernet MAC & PHY.
++
++config MICROTRONIX_STRATIX
++ bool "Microtronix Stratix board support"
++ depends on NIOS2
++ help
++ Support for the Microtronix Stratix board. Includes support
++ for Sodimm SDRAM/FLASH, soft ethernet MAC & PHY, USB, LVDS
++ & analog/digital converters.
++
++config MICROTRONIX_CYCLONE
++ bool "Microtronix Cyclone board support"
++ depends on NIOS2
++ help
++ Support for the Microtronix Cyclone board. Includes support
++ for SDRAM, FLASH, soft ethernet MAC & PHY, USB,
++ & analog/digital converters.
++
++config MICROTRONIX_PSK
++ bool "Microtronix PSK (Product Starter Kit) support"
++ depends on NIOS2
++ help
++ Support for the Microtronix PSK (Product Starter Kit), which
++ features firefly module (EP1C4 or EP1C12). Includes support
++ for SDRAM, FLASH, and a variety of product expansion kits such
++ as USB, Ethernet etc.
++
++config ALTERA_STRATIX
++ bool "Altera Stratix Development board support"
++ depends on NIOS2
++ help
++ Support for the Altera Stratix Development board. Includes
++ support for 10/100 ethernet, FLASH, SDRAM, compact flash.
++
++config ALTERA_STRATIX_PRO
++ bool "Altera Stratix Pro Development board support"
++ depends on NIOS2
++ help
++ Support for the Altera Stratix 1s40 Development board. Includes
++ support for 10/100 ethernet, FLASH, SDRAM, compact flash.
++
++config ALTERA_STRATIX_II
++ bool "Altera Stratix II Development board support"
++ depends on NIOS2
++ help
++ Support for the Altera Stratix II Development board. Includes
++ support for 10/100 ethernet, FLASH, SDRAM, compact flash.
++
++config ALTERA_CYCLONE
++ bool "Altera Cyclone Development board support"
++ depends on NIOS2
++ help
++ Support for the Altera Cyclone Development board. Includes
++ support for 10/100 ethernet, FLASH, SDRAM, compact flash.
++
++config ALTERA_CYCLONE_1C12_EVAL
++ bool "Altera Cyclone 1C12 Evaluation board support"
++ depends on NIOS2
++ help
++ Support for the Altera Cyclone 1C12 Evaluation board (with the
++ embedded processor module).
++
++config ALTERA_DE2
++ bool "Altera DE2 Development board support"
++ depends on NIOS2
++ help
++ Support for the Altera Cyclone Development board. Includes
++ support for 10/100 ethernet, FLASH, SDRAM, VGA, I2C.
++
++endchoice
++
++choice
++ prompt "Nios II Hardware Multiply Support"
++ default NIOS2_HW_MULX
++ help
++ This option enables various assembler instructions based on your
++ selection. The choice depends on what target hardware you'll be
++ running your applications on. The default is
++ "Enable mulx instruction".
++
++ Here is an explanation of each option:
++ None = -mno-hw-mul -mno-hw-mulx
++ (no mul or mulx instructions used)
++ Enable mul instruction = -mhw-mul -mno-hw-mulx
++ (use mul instructions)
++ Enable mul and mulx instructions = -mhw-mul -mhw-mulx
++ (use mul and mulx instructions)
++
++ If you don't know what to choose, select "Enable mulx instruction".
++
++config NIOS2_HW_MUL_OFF
++ bool "None"
++
++config NIOS2_HW_MUL
++ bool "Enable mul instruction"
++
++config NIOS2_HW_MULX
++ bool "Enable mul and mulx instructions"
++
++endchoice
++
++comment 'Platform drivers Options'
++
++config AVALON_DMA
++ bool "Support of DMA controller with Avalon interface"
++ default y
++ help
++ This enables support of Altera's DMA controller with Avalon
++ interface, so that drivers of DMA-able device can use this
++ interface.
++
++config PIO_DEVICES
++ bool "Enable leds, seven segment display"
++ default y
++ depends on (ALTERA_STRATIX || ALTERA_STRATIX_PRO || ALTERA_CYCLONE)
++ help
++ This enables example code to support leds, and seven segment
++ display as PIO devices. Once enabled, the kernel will show a
++ counter (increas once a second) on these devices.
++
++source "arch/nios2nommu/drivers/Kconfig"
++
++comment 'Miscellaneous Options'
++
++config EXCALIBUR
++ bool
++ default y
++ depends on (NIOS2)
++
++config BREAK_ON_START
++ bool "Include breakpoint trap on kernel startup"
++ help
++ Configures the kernel to trap to the GDB client on startup
++ before the kernel starts initialization. This allows you to
++ debug the kernel startup.
++
++config LARGE_ALLOCS
++ bool "Allow allocating large blocks (> 1MB) of memory"
++ help
++ Allow the slab memory allocator to keep chains for very large
++ memory sizes - upto 32MB. You may need this if your system has
++ a lot of RAM, and you need to able to allocate very large
++ contiguous chunks. If unsure, say N.
++
++choice
++ prompt "Kernel executes from"
++ ---help---
++ Choose the memory type that the kernel will be running in.
++
++config RAMKERNEL
++ bool "RAM"
++ help
++ The kernel will be resident in RAM when running.
++
++#config ROMKERNEL
++# bool "ROM"
++# help
++# The kernel will be resident in FLASH/ROM when running.
++
++#config HIMEMKERNEL
++# bool "HIMEM"
++# help
++# The kernel will be resident in high memory when running.
++
++endchoice
++
++config PREEMPT
++ bool "Preemptible Kernel"
++ help
++ This option reduces the latency of the kernel when reacting to
++ real-time or interactive events by allowing a low priority process to
++ be preempted even if it is in kernel mode executing a system call.
++ This allows applications to run more reliably even when the system is
++ under load.
++
++ Say Y here if you are building a kernel for a desktop, embedded
++ or real-time system. Say N if you are unsure.
++
++config PREEMPT_TIMES
++ bool "Collect preemption latency times"
++ depends on PREEMPT
++ help
++ Allow collection for preemption latency times.
++
++config CMDLINE
++ string "Default kernel command string"
++ default "CONSOLE=/dev/ttyS0 root=/dev/rom0 ro"
++ help
++ On some architectures, 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 PASS_CMDLINE
++ bool "Passed kernel command line from u-boot"
++ default n
++ help
++ Use bootargs env variable from u-boot for kernel command line.
++ will override "Default kernel command string".
++ Say N if you are unsure.
++
++source "mm/Kconfig"
++
++config BOOT_LINK_OFFSET
++ hex "Link address offset for booting"
++ default "0x00800000"
++ help
++ This option allows you to set the link address offset of the zImage.
++ This can be useful if you are on a board which has a small amount of
++ memory.
++
++endmenu
++
++menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
++
++config PCI
++ bool "PCI support"
++ help
++ Support for PCI bus.
++
++source "drivers/pci/Kconfig"
++
++config HOTPLUG
++ bool "Support for hot-pluggable device"
++ ---help---
++ Say Y here if you want to plug devices into your computer while
++ the system is running, and be able to use them quickly. In many
++ cases, the devices can likewise be unplugged at any time too.
++
++ One well known example of this is PCMCIA- or PC-cards, credit-card
++ size devices such as network cards, modems or hard drives which are
++ plugged into slots found on all modern laptop computers. Another
++ example, used on modern desktops as well as laptops, is USB.
++
++ Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
++ software (at <http://linux-hotplug.sourceforge.net/>) and install it.
++ Then your kernel will automatically call out to a user mode "policy
++ agent" (/sbin/hotplug) to load modules and set up software needed
++ to use devices as you hotplug them.
++
++source "drivers/pcmcia/Kconfig"
++
++source "drivers/pci/hotplug/Kconfig"
++
++endmenu
++
++menu "Executable file formats"
++
++config KCORE_AOUT
++ bool
++ default y
++
++config KCORE_ELF
++ bool
++ default y
++
++source "fs/Kconfig.binfmt"
++
++endmenu
++
++menu "Power management options"
++
++config PM
++ bool "Power Management support"
++ help
++ Support processor power management modes
++
++endmenu
++
++
++source "net/Kconfig"
++
++source "drivers/Kconfig"
++
++source "fs/Kconfig"
++
++source "arch/nios2nommu/Kconfig.debug"
++
++menu "Kernel hacking"
++
++config FULLDEBUG
++ bool "Full Symbolic/Source Debugging support"
++ help
++ Enable debuging symbols on kernel build.
++
++config FRAME_POINTER
++ bool "Compile the kernel with frame pointers"
++ help
++ If you say Y here the resulting kernel image will be slightly larger
++ and slower, but it will give very useful debugging information.
++ If you don't debug the kernel, you can say N, but we may not be able
++ to solve problems without frame pointers.
++
++config MAGIC_SYSRQ
++ bool "Magic SysRq key"
++ help
++ Enables console device to interpret special characters as
++ commands to dump state information.
++
++config HIGHPROFILE
++ bool "Use fast second timer for profiling"
++ depends on COLDFIRE
++ help
++ Use a fast secondary clock to produce profiling information.
++
++config NO_KERNEL_MSG
++ bool "Suppress Kernel BUG Messages"
++ help
++ Do not output any debug BUG messages within the kernel.
++
++config LOG_BUF_SHIFT
++ int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
++ range 12 21
++ default 17 if ARCH_S390
++ default 16 if X86_NUMAQ || IA64
++ default 15 if SMP
++ default 14
++ help
++ Select kernel log buffer size as a power of 2.
++ Defaults and Examples:
++ 17 => 128 KB for S/390
++ 16 => 64 KB for x86 NUMAQ or IA-64
++ 15 => 32 KB for SMP
++ 14 => 16 KB for uniprocessor
++ 13 => 8 KB
++ 12 => 4 KB
++
++endmenu
++
++source "security/Kconfig"
++
++source "crypto/Kconfig"
++
++source "lib/Kconfig"
+diff --git a/arch/nios2nommu/Kconfig.debug b/arch/nios2nommu/Kconfig.debug
+new file mode 100644
+index 0000000..b188c4a
+--- /dev/null
++++ b/arch/nios2nommu/Kconfig.debug
+@@ -0,0 +1,35 @@
++menu "Kernel hacking"
++
++source "lib/Kconfig.debug"
++
++config FULLDEBUG
++ bool "Full Symbolic/Source Debugging support"
++ help
++ Enable debuging symbols on kernel build.
++
++config FRAME_POINTER
++ bool "Compile the kernel with frame pointers"
++ help
++ If you say Y here the resulting kernel image will be slightly larger
++ and slower, but it will give very useful debugging information.
++ If you don't debug the kernel, you can say N, but we may not be able
++ to solve problems without frame pointers.
++
++config MAGIC_SYSRQ
++ bool "Magic SysRq key"
++ help
++ Enables console device to interpret special characters as
++ commands to dump state information.
++
++config HIGHPROFILE
++ bool "Use fast second timer for profiling"
++ depends on COLDFIRE
++ help
++ Use a fast secondary clock to produce profiling information.
++
++config NO_KERNEL_MSG
++ bool "Suppress Kernel BUG Messages"
++ help
++ Do not output any debug BUG messages within the kernel.
++
++endmenu
+diff --git a/arch/nios2nommu/Makefile b/arch/nios2nommu/Makefile
+new file mode 100644
+index 0000000..ca139b6
+--- /dev/null
++++ b/arch/nios2nommu/Makefile
+@@ -0,0 +1,181 @@
++# arch/niosnommu/Makefile
++#
++# Makefile for the architecture dependent flags and dependencies on the
++# nios.
++#
++# Copyright (C) 2001 Vic Phillips (vic@microtronix.com)
++#
++# based on sparcnommu/Makefile:
++#
++# Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
++#
++KERNELLOAD = ${shell echo `grep "nasys_program_mem " include/asm/nios.h | sed 's/^.*\*)//' | sed 's/)//'`}
++
++HARDWARE_MK = arch/$(ARCH)/hardware.mk
++
++platform-$(CONFIG_NIOS) := NIOS2
++PLATFORM := $(platform-y)
++
++board-$(CONFIG_ALTERA_STRATIX) := altera_stratix
++board-$(CONFIG_ALTERA_STRATIX_PRO) := altera_stratix_pro
++board-$(CONFIG_ALTERA_STRATIX_II) := altera_stratix_ii
++board-$(CONFIG_ALTERA_CYCLONE) := altera_cyclone
++board-$(CONFIG_ALTERA_CYCLONE_1C12_EVAL) := altera_cyclone_1c12_eval
++board-$(CONFIG_MICROTRONIX_STRATIX) := microtronix_stratix
++board-$(CONFIG_MICROTRONIX_CYCLONE) := microtronix_cyclone
++board-$(CONFIG_MICROTRONIX_UKIT) := microtronix_ukit
++board-$(CONFIG_MICROTRONIX_PSK) := microtronix_psk
++BOARD := $(board-y)
++
++model-$(CONFIG_RAMKERNEL) := ram
++model-$(CONFIG_ROMKERNEL) := rom
++model-$(CONFIG_HIMEMKERNEL) := himem
++MODEL := $(model-y)
++
++export PLATFORM BOARD MODEL
++
++CFLAGS += -DNO_MM -pipe -D__linux__ -D__ELF__
++#CFLAGS += -DNO_MM -save-temps -D__linux__ -D__ELF__
++
++# Uncomment this if you are doing gdb source level
++# debugging of the kernel to get the proper debugging information.
++#
++#CFLAGS += -DDEBUG
++
++# Turn on/off various hardware multiply options
++cpu-cflags-$(CONFIG_NIOS2_HW_MUL_OFF) += -mno-hw-mul -mno-hw-mulx
++cpu-cflags-$(CONFIG_NIOS2_HW_MUL) += -mhw-mul -mno-hw-mulx
++cpu-cflags-$(CONFIG_NIOS2_HW_MULX) += -mhw-mul -mhw-mulx
++CFLAGS += $(cpu-cflags-y)
++
++# mulx flags currently cause older version of nios2-elf-gcc to fail
++# The following line ensures that all mulx flags are removed before
++# it is passed to the compiler.
++mulx_help_text:= $(shell $(CC) --target-help | grep mulx)
++ifeq "$(mulx_help_text)" ""
++CFLAGS := $(filter-out -mhw-mulx -mno-hw-mulx, $(CFLAGS))
++endif
++
++# Temporary workaround for nios2-elf-gcc bug
++# First noticed in v3.4.1 (Altera Nios II 1.1 b131)
++# To be removed at a later date when bug is resolved.
++CFLAGS += -fno-optimize-sibling-calls
++
++# This undefines the "__init" type used in defining initialization
++# procedures. When defined, the procedures are put into an 'init' data
++# section that GDB doesn't recognize as source.
++#
++CFLAGS += -DNO_TEXT_SECTIONS
++CFLAGS += -fno-builtin
++CFLAGS += -O2 -g -G 0
++CFLAGS += -DUTS_SYSNAME=\"uClinux\"
++
++CFLAGS_GCC_INC := $(shell $(CC) -print-file-name=include)
++CFLAGS += -I$(CFLAGS_GCC_INC)
++
++AFLAGS += -DNO_MM -g
++#AFLAGS += -DNO_MM -g -save-temps
++
++# vic - add this to get name of nios gcc library
++LIBGCC_CFLAGS = $(if $(CONFIG_NIOS2_HW_MUL_OFF),-mno-hw-mul)
++LIBGCC := `$(CC) --print-libgcc-file-name $(LIBGCC_CFLAGS)`
++
++# add this to avoid multiple '_stack' and '_vecbase' definition errors
++#
++ifdef niosgnu
++# Include the path to the lib directory where the ldscripts are found to fix
++# a problem with the cygwin/bash environment.
++
++#cygwhack: kenw - this following section could be a possible problem
++# due to the O= option on the command line.
++LDSCRIPTS:=$(shell nios2-elf-gcc -print-file-name=ldscripts)
++LDFLAGS += -mnios2elf -L $(LDSCRIPTS)/..
++else
++LDFLAGS += -mnios2elf
++LDLIBS := -L `$(CC) -print-file-name=m32` -l gcc
++endif
++
++head-y := arch/nios2nommu/kernel/head.o arch/nios2nommu/kernel/init_task.o
++
++CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \
++ $(HARDWARE_MK) \
++ arch/$(ARCH)/kernel/asm-offsets.s \
++ linux.srec \
++ linux.flash \
++ linux.bin \
++ linux.bin.srec
++
++core-y += arch/nios2nommu/kernel/ \
++ arch/nios2nommu/mm/ \
++ arch/nios2nommu/drivers/
++
++libs-y += arch/nios2nommu/lib/
++
++libs-y += $(LIBGCC)
++####;dgt2;tmp;
++
++# force user to configure hardware before building kernel
++
++pardoned_targets = clean mrproper sgmldocs psdocs pdfdocs \
++ htmldocs mandocs headers_install
++
++-include $(HARDWARE_MK)
++build_targets = $(filter-out $(pardoned_targets), $(MAKECMDGOALS))
++ifneq '$(strip $(build_targets))' ''
++ ifndef SYSPTF
++ ifneq '$(firstword $(MAKECMDGOALS))' 'hwselect'
++ $(error Run "make hwselect SYSPTF=<system.ptf>" first)
++ endif
++ endif
++endif
++
++quiet_cmd_gen_mk = ' RUNNING $@'
++define cmd_gen_mk
++ mkdir -p $(dir $(objtree)/$(HARDWARE_MK)); \
++ perl -I$(TOPDIR)/arch/$(ARCH)/scripts \
++ $(srctree)/arch/$(ARCH)/scripts/hwselect.pl $(SYSPTF) \
++ $(objtree)/$(HARDWARE_MK)
++endef
++
++.PHONY: hwselect
++hwselect:
++ @echo $($(quiet)cmd_gen_mk);
++ @$(cmd_gen_mk)
++
++prepare: include/nios2_system.h
++
++archclean:
++ $(call descend arch/$(ARCH)/boot, subdirclean)
++
++define filechk_nios2_system.h
++ # call perl script that will build nios2_system.h file
++ perl -I$(TOPDIR)/arch/$(ARCH)/scripts \
++ $(TOPDIR)/arch/$(ARCH)/scripts/gen_nios2_system.h.pl $(CPU) $(EXEMEM) $(UPLMEM)
++endef
++
++include/nios2_system.h: $(SYSPTF) FORCE
++ $(call filechk,nios2_system.h)
++
++quiet_cmd_touch = ' TOUCH $@'
++ cmd_touch = touch $(TOPDIR)/$@
++
++arch/$(ARCH)/kernel/vmlinux.lds.S: FORCE
++ @echo $($(quiet)cmd_touch);
++ @$(cmd_touch)
++
++linuxsrec: linux
++ $(OBJCOPY) -O srec $(LINUX) linux.srec
++
++boot := arch/nios2nommu/boot
++
++zImage: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
++
++compressed: zImage
++
++CLEAN_FILES += include/nios2_system.h
++
++archmrproper:
++
++archdep:
++
+diff --git a/arch/nios2nommu/boot/Makefile b/arch/nios2nommu/boot/Makefile
+new file mode 100644
+index 0000000..fd25b72
+--- /dev/null
++++ b/arch/nios2nommu/boot/Makefile
+@@ -0,0 +1,17 @@
++#
++# arch/nios2nommu/boot/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++
++targets := zImage
++subdir- := compressed
++
++$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
++ $(call if_changed,objcopy)
++ @echo 'Kernel: $@ is ready'
++
++$(obj)/compressed/vmlinux: FORCE
++ $(Q)$(MAKE) $(build)=$(obj)/compressed $@
++
+diff --git a/arch/nios2nommu/boot/compressed/Makefile b/arch/nios2nommu/boot/compressed/Makefile
+new file mode 100644
+index 0000000..2002471
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/Makefile
+@@ -0,0 +1,36 @@
++#
++# linux/arch/sh/boot/compressed/Makefile
++#
++# create a compressed vmlinux image from the original vmlinux
++#
++
++targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \
++ piggy.o vmlinux.lds
++EXTRA_AFLAGS :=
++
++OBJECTS = $(obj)/head.o $(obj)/misc.o
++
++#
++# IMAGE_OFFSET is the load offset of the compression loader
++#
++#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x2000])
++#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x00400000])
++
++LDFLAGS_vmlinux := -T
++
++$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
++ $(call if_changed,ld)
++ @:
++
++$(obj)/vmlinux.bin: vmlinux FORCE
++ $(call if_changed,objcopy)
++
++$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
++ $(call if_changed,gzip)
++
++LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T
++
++OBJCOPYFLAGS += -O binary
++
++$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
++ $(call if_changed,ld)
+diff --git a/arch/nios2nommu/boot/compressed/head.S b/arch/nios2nommu/boot/compressed/head.S
+new file mode 100644
+index 0000000..accadd0
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/head.S
+@@ -0,0 +1,100 @@
++/*
++ * linux/arch/nios2nommu/boot/compressed/head.S
++ *
++ */
++
++ .text
++ .set noat
++#include <asm/asm-offsets.h>
++#include <asm/asm-macros.h>
++
++ /*
++ * This code can be loaded anywhere, as long as output will not
++ * overlap it.
++ *
++ */
++
++ .global _start
++_start:
++ // disable interrupt
++ wrctl status, r0
++ // flush the instruction cache
++ movia r1,NIOS2_ICACHE_SIZE
++ movi r2,NIOS2_ICACHE_LINE_SIZE
++text_init:
++ initi r1
++ sub r1, r1, r2
++ bgt r1, zero, text_init
++ // then flush the pipeline
++ flushp
++ // flush the data cache
++ movia r1,NIOS2_DCACHE_SIZE
++ movi r2,NIOS2_DCACHE_LINE_SIZE
++data_init:
++ initd (r1)
++ sub r1, r1, r2
++ bgt r1, zero, data_init
++ //------------------------------------------------------
++ // Zero out the .bss segment (uninitialized common data)
++ //
++ movia r2,__bss_start // presume nothing is between
++ movia r1,_end // the .bss and _end.
++1:
++ stb r0,0(r2)
++ addi r2,r2,1
++ bne r1,r2,1b
++ // set up the stack pointer, some where higher than _end. The stack space must be greater than 32K for decompress.
++ movia sp, 0x10000
++ add sp,sp,r1
++ // save args passed from u-boot
++ addi sp,sp,-16
++ stw r4,0(sp)
++ stw r5,4(sp)
++ stw r6,8(sp)
++ stw r7,12(sp)
++/*
++ * decompress the kernel
++ */
++ call decompress_kernel
++
++flush_cache:
++ // flush all cache after loading
++ // flush the data cache
++ movia r1,NIOS2_DCACHE_SIZE
++ movi r2,NIOS2_DCACHE_LINE_SIZE
++data_flush:
++ flushd (r1)
++ sub r1, r1, r2
++ bgt r1, zero, data_flush
++ // flush the instruction cache
++ movia r1,NIOS2_ICACHE_SIZE
++ movi r2,NIOS2_ICACHE_LINE_SIZE
++text_flush:
++ flushi r1
++ sub r1, r1, r2
++ bgt r1, zero, text_flush
++ // then flush the pipeline
++ flushp
++ // pass saved args to kernel
++ ldw r4,0(sp)
++ ldw r5,4(sp)
++ ldw r6,8(sp)
++ ldw r7,12(sp)
++ movia r1,LINUX_SDRAM_START
++ jmp r1
++
++ .balign 512
++fake_headers_as_bzImage:
++ .short 0
++ .ascii "HdrS"
++ .short 0x0202
++ .short 0
++ .short 0
++ .byte 0x00, 0x10
++ .short 0
++ .byte 0
++ .byte 1
++ .byte 0x00, 0x80
++ .long 0
++ .long 0
++
+diff --git a/arch/nios2nommu/boot/compressed/install.sh b/arch/nios2nommu/boot/compressed/install.sh
+new file mode 100644
+index 0000000..6d72e9e
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/install.sh
+@@ -0,0 +1,57 @@
++#!/bin/sh
++#
++# arch/sh/boot/install.sh
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 1995 by Linus Torvalds
++#
++# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
++# Adapted from code in arch/i386/boot/install.sh by Russell King
++# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
++# Adapted from code in arch/sh/boot/install.sh by Takeo Takahashi
++#
++# "make install" script for sh architecture
++#
++# Arguments:
++# $1 - kernel version
++# $2 - kernel image file
++# $3 - kernel map file
++# $4 - default install path (blank if root directory)
++#
++
++# User may have a custom install script
++
++if [ -x /sbin/installkernel ]; then
++ exec /sbin/installkernel "$@"
++fi
++
++if [ "$2" = "zImage" ]; then
++# Compressed install
++ echo "Installing compressed kernel"
++ if [ -f $4/vmlinuz-$1 ]; then
++ mv $4/vmlinuz-$1 $4/vmlinuz.old
++ fi
++
++ if [ -f $4/System.map-$1 ]; then
++ mv $4/System.map-$1 $4/System.old
++ fi
++
++ cat $2 > $4/vmlinuz-$1
++ cp $3 $4/System.map-$1
++else
++# Normal install
++ echo "Installing normal kernel"
++ if [ -f $4/vmlinux-$1 ]; then
++ mv $4/vmlinux-$1 $4/vmlinux.old
++ fi
++
++ if [ -f $4/System.map ]; then
++ mv $4/System.map $4/System.old
++ fi
++
++ cat $2 > $4/vmlinux-$1
++ cp $3 $4/System.map
++fi
+diff --git a/arch/nios2nommu/boot/compressed/misc.c b/arch/nios2nommu/boot/compressed/misc.c
+new file mode 100644
+index 0000000..c513e6e
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/misc.c
+@@ -0,0 +1,208 @@
++/*
++ * arch/nios2nommu/boot/compressed/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
++ *
++ * Adapted for SH by Stuart Menefy, Aug 1999
++ *
++ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
++ */
++
++#include <linux/string.h>
++
++/*
++ * gzip declarations
++ */
++
++#define OF(args) args
++#define STATIC static
++
++#undef memset
++#undef memcpy
++#define memzero(s, n) memset ((s), 0, (n))
++
++typedef unsigned char uch;
++typedef unsigned short ush;
++typedef unsigned long ulg;
++
++#define WSIZE 0x8000 /* Window size must be at least 32k, */
++ /* and a power of two */
++
++static uch *inbuf; /* input buffer */
++static uch window[WSIZE]; /* Sliding window buffer */
++
++static unsigned insize = 0; /* valid bytes in inbuf */
++static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
++static unsigned outcnt = 0; /* bytes in output buffer */
++
++/* 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 */
++
++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
++
++/* Diagnostic functions */
++#ifdef DEBUG
++# define Assert(cond,msg) {if(!(cond)) error(msg);}
++# define Trace(x) fprintf x
++# define Tracev(x) {if (verbose) fprintf x ;}
++# define Tracevv(x) {if (verbose>1) fprintf x ;}
++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#else
++# define Assert(cond,msg)
++# define Trace(x)
++# define Tracev(x)
++# define Tracevv(x)
++# define Tracec(c,x)
++# define Tracecv(c,x)
++#endif
++
++static int fill_inbuf(void);
++static void flush_window(void);
++static void error(char *m);
++static void gzip_mark(void **);
++static void gzip_release(void **);
++
++extern char input_data[];
++extern int input_len;
++
++static long bytes_out = 0;
++static uch *output_data;
++static unsigned long output_ptr = 0;
++
++#include "nios2_sio.c"
++
++static void *malloc(int size);
++static void free(void *where);
++static void error(char *m);
++static void gzip_mark(void **);
++static void gzip_release(void **);
++
++int puts(const char *);
++
++extern int _end;
++static unsigned long free_mem_ptr;
++static unsigned long free_mem_end_ptr;
++
++#define HEAP_SIZE 0x10000
++
++#include "../../../../lib/inflate.c"
++
++static void *malloc(int size)
++{
++ void *p;
++
++ if (size <0) error("Malloc error");
++ if (free_mem_ptr == 0) error("Memory error");
++
++ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
++
++ p = (void *)free_mem_ptr;
++ free_mem_ptr += size;
++
++ if (free_mem_ptr >= free_mem_end_ptr)
++ error("Out of memory");
++
++ return p;
++}
++
++static void free(void *where)
++{ /* Don't care */
++}
++
++static void gzip_mark(void **ptr)
++{
++ *ptr = (void *) free_mem_ptr;
++}
++
++static void gzip_release(void **ptr)
++{
++ free_mem_ptr = (long) *ptr;
++}
++
++void* memset(void* s, int c, size_t n)
++{
++ int i;
++ char *ss = (char*)s;
++
++ for (i=0;i<n;i++) ss[i] = c;
++ return s;
++}
++
++void* memcpy(void* __dest, __const void* __src,
++ size_t __n)
++{
++ int i;
++ char *d = (char *)__dest, *s = (char *)__src;
++
++ for (i=0;i<__n;i++) d[i] = s[i];
++ return __dest;
++}
++
++/* ===========================================================================
++ * Fill the input buffer. This is called only when the buffer is empty
++ * and at least one byte is really needed.
++ */
++static int fill_inbuf(void)
++{
++ if (insize != 0) {
++ error("ran out of input data");
++ }
++
++ inbuf = input_data;
++ insize = input_len;
++ inptr = 1;
++ return inbuf[0];
++}
++
++/* ===========================================================================
++ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
++ * (Used for the decompressed data only.)
++ */
++static void flush_window(void)
++{
++ ulg c = crc; /* temporary variable */
++ unsigned n;
++ uch *in, *out, ch;
++ in = window;
++ out = &output_data[output_ptr];
++ for (n = 0; n < outcnt; n++) {
++ ch = *out++ = *in++;
++ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
++ }
++ crc = c;
++ bytes_out += (ulg)outcnt;
++ output_ptr += (ulg)outcnt;
++ outcnt = 0;
++}
++
++static void error(char *x)
++{
++ puts("\nERROR\n");
++ puts(x);
++ puts("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++void decompress_kernel(void)
++{
++ output_data = (void *)nasys_program_mem;
++ output_ptr = 0;
++ free_mem_ptr = (unsigned long)&_end;
++ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
++
++ makecrc();
++ puts("Uncompressing Linux... ");
++ gunzip();
++ puts("Ok, booting the kernel.\n");
++}
+diff --git a/arch/nios2nommu/boot/compressed/nios2_sio.c b/arch/nios2nommu/boot/compressed/nios2_sio.c
+new file mode 100644
+index 0000000..8630c8f
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/nios2_sio.c
+@@ -0,0 +1,57 @@
++
++static int putchar(int ch);
++
++static int puts(const char *s)
++ {
++ while(*s)
++ putchar(*s++);
++ return 0;
++ }
++
++#include <asm/nios.h>
++#include <asm/io.h>
++
++#if defined(CONFIG_SERIAL_AJUART_CONSOLE)
++
++#define IORD_ALTERA_AVALON_JTAG_UART_DATA(base) inl(base)
++#define IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, data) outl(data, base)
++#define IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base) inl(base+4)
++#define IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(base, data) outl(data, base+4)
++#define ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK (0xFFFF0000u)
++#define ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST (16)
++
++static void jtag_putc(int ch)
++{
++ unsigned base = na_jtag_uart;
++ while ((IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base) & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) == 0);
++ IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, ch);
++}
++
++static int putchar(int ch)
++{
++ jtag_putc( ch );
++ return ch;
++}
++
++#elif defined(CONFIG_NIOS_SERIAL_CONSOLE)
++
++static void nr_txchar(int ch)
++{
++ while ((na_uart0->np_uartstatus & np_uartstatus_trdy_mask) == 0);
++ na_uart0->np_uarttxdata = ch;
++}
++
++static int putchar(int ch)
++{
++ nr_txchar( ch ); if (ch=='\n') nr_txchar( '\r' );
++ return ch;
++}
++
++#else
++
++static int putchar(int ch)
++{
++ return ch;
++}
++
++#endif
+diff --git a/arch/nios2nommu/boot/compressed/vmlinux.lds.S b/arch/nios2nommu/boot/compressed/vmlinux.lds.S
+new file mode 100644
+index 0000000..08bb3e2
+--- /dev/null
++++ b/arch/nios2nommu/boot/compressed/vmlinux.lds.S
+@@ -0,0 +1,34 @@
++#include <asm-generic/vmlinux.lds.h>
++#include <asm/nios.h>
++
++OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
++
++OUTPUT_ARCH(nios)
++ENTRY(_start) /* Defined in head.S */
++
++SECTIONS
++{
++ . =nasys_program_mem + CONFIG_BOOT_LINK_OFFSET;
++
++ _text = .;
++ .text : { *(.text) } = 0
++ .rodata : { *(.rodata) *(.rodata.*) }
++ _etext = .;
++
++ . = ALIGN(32 / 8);
++ .data : { *(.data) }
++ . = ALIGN(32 / 8);
++ _got = .;
++ .got : { *(.got) _egot = .; *(.got.*) }
++ _edata = .;
++
++ . = ALIGN(32 / 8);
++ __bss_start = .;
++ .bss : { *(.bss) *(.sbss) }
++ . = ALIGN(32 / 8);
++ _ebss = .;
++ end = . ;
++ _end = . ;
++
++ got_len = (_egot - _got);
++}
+diff --git a/arch/nios2nommu/defconfig b/arch/nios2nommu/defconfig
+new file mode 100644
+index 0000000..40629cb
+--- /dev/null
++++ b/arch/nios2nommu/defconfig
+@@ -0,0 +1,690 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.19-uc1
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_SYSVIPC is not set
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++# CONFIG_RELAY is not set
++CONFIG_INITRAMFS_SOURCE="../romfs ../vendors/Altera/nios2nommu/romfs_list"
++CONFIG_INITRAMFS_ROOT_UID=500
++CONFIG_INITRAMFS_ROOT_GID=500
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_EMBEDDED=y
++# CONFIG_SYSCTL_SYSCALL is not set
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++# CONFIG_ELF_CORE is not set
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++# CONFIG_EPOLL is not set
++CONFIG_SLAB=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++# CONFIG_SLOB is not set
++
++#
++# Loadable module support
++#
++# CONFIG_MODULES is not set
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++CONFIG_DEFAULT_DEADLINE=y
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="deadline"
++
++#
++# Processor type and features
++#
++
++#
++# Platform dependant setup
++#
++CONFIG_NIOS2=y
++# CONFIG_MICROTRONIX_UKIT is not set
++# CONFIG_MICROTRONIX_STRATIX is not set
++# CONFIG_MICROTRONIX_CYCLONE is not set
++# CONFIG_MICROTRONIX_PSK is not set
++CONFIG_ALTERA_STRATIX=y
++# CONFIG_ALTERA_STRATIX_PRO is not set
++# CONFIG_ALTERA_STRATIX_II is not set
++# CONFIG_ALTERA_CYCLONE is not set
++# CONFIG_ALTERA_CYCLONE_1C12_EVAL is not set
++# CONFIG_ALTERA_DE2 is not set
++# CONFIG_NIOS2_HW_MUL_OFF is not set
++CONFIG_NIOS2_HW_MUL=y
++# CONFIG_NIOS2_HW_MULX is not set
++
++#
++# Platform drivers Options
++#
++# CONFIG_AVALON_DMA is not set
++# CONFIG_PIO_DEVICES is not set
++# CONFIG_PCI is not set
++# CONFIG_FB_ALTERA is not set
++# CONFIG_SERIO_ALTPS2 is not set
++# CONFIG_I2C_GPIO is not set
++
++#
++# Miscellaneous Options
++#
++CONFIG_EXCALIBUR=y
++# CONFIG_BREAK_ON_START is not set
++CONFIG_LARGE_ALLOCS=y
++CONFIG_RAMKERNEL=y
++CONFIG_PREEMPT=y
++# CONFIG_PREEMPT_TIMES is not set
++CONFIG_CMDLINE=""
++# CONFIG_PASS_CMDLINE 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_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_BOOT_LINK_OFFSET=0x00500000
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# PCI Hotplug Support
++#
++
++#
++# Executable file formats
++#
++CONFIG_KCORE_AOUT=y
++CONFIG_KCORE_ELF=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++# CONFIG_NETDEBUG is not set
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPSEC_NAT_TRAVERSAL is not set
++# 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_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++
++#
++# DCCP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_DCCP is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++
++#
++# TIPC Configuration (EXPERIMENTAL)
++#
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_KLIPS is not set
++# CONFIG_IEEE80211 is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++# CONFIG_MTD is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_TIFM_CORE is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++
++#
++# Serial ATA (prod) and Parallel ATA (experimental) drivers
++#
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# PHY device support
++#
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_NET_VENDOR_SMC is not set
++# CONFIG_OPEN_ETH is not set
++# CONFIG_MTIP1000_ETH is not set
++# CONFIG_NE2000 is not set
++# CONFIG_NET_PCI is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NIOS_LCD_16207 is not set
++# CONFIG_NIOS_BUTTON is not set
++# CONFIG_LEDMAN is not set
++# CONFIG_SNAPDOG is not set
++# CONFIG_FAST_TIMER is not set
++# CONFIG_RESETSWITCH is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_NIOS_SERIAL is not set
++CONFIG_SERIAL_AJUART=y
++CONFIG_SERIAL_AJUART_CONSOLE=y
++# CONFIG_UNIX98_PTYS is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=10
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_RTC is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_M41T11M6 is not set
++
++#
++# I2C support
++#
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# 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_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_INOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++# CONFIG_DIRECTIO is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_SYSCTL is not set
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=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_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Debug
++#
++# CONFIG_COREDUMP_PRINTK is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_FULLDEBUG is not set
++# CONFIG_FRAME_POINTER is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_NO_KERNEL_MSG is not set
++CONFIG_LOG_BUF_SHIFT=14
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
+diff --git a/arch/nios2nommu/drivers/Kconfig b/arch/nios2nommu/drivers/Kconfig
+new file mode 100644
+index 0000000..2fde3a8
+--- /dev/null
++++ b/arch/nios2nommu/drivers/Kconfig
+@@ -0,0 +1,45 @@
++# Platfrom drivers configuration
++
++source "arch/nios2nommu/drivers/pci/Kconfig"
++
++config FB_ALTERA
++ tristate "Avalon VGA controller support"
++ default N
++ select FB
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ help
++ This is the frame buffer device driver for the VGA controller
++ in SOPC Builder.
++
++config SERIO_ALTPS2
++ tristate "PS2 controller"
++ select VT
++ default N
++ select SERIO
++
++config I2C_NIOS2_GPIO
++ tristate "GPIO-Based I2C Interface"
++ default N
++ select I2C
++ select I2C_ALGOBIT
++ help
++ Say Y here if you use GPIO lines for an I2C bus.
++
++config BLK_DEV_ALTCF
++ tristate "Altera CF (IDE mode) interface (Avalon bus) support"
++ select IDE
++ select BLK_DEV_IDE
++ default N
++ help
++ This driver provides support for the Altera Compact flash core (with
++ Avalon interface) support. If you have an Altera or Microtronix
++ development board you can build support into the FPGA device for this.
++
++config NIOS_SPI
++ bool "Nios SPI device support"
++ depends on NIOS || NIOS2
++ help
++ This driver supports the Nios softcore SPI device.
++
+diff --git a/arch/nios2nommu/drivers/Makefile b/arch/nios2nommu/drivers/Makefile
+new file mode 100644
+index 0000000..f6a273e
+--- /dev/null
++++ b/arch/nios2nommu/drivers/Makefile
+@@ -0,0 +1,10 @@
++#
++# Makefile for the Linux nios2-specific device drivers.
++#
++
++obj-$(CONFIG_PCI) += pci/
++obj-$(CONFIG_FB_ALTERA) += altfb.o
++obj-$(CONFIG_SERIO_ALTPS2) += altps2.o
++obj-$(CONFIG_I2C_NIOS2_GPIO) += i2c-gpio.o
++obj-$(CONFIG_BLK_DEV_ALTCF) += altcf.o
++obj-$(CONFIG_NIOS_SPI) += spi.o
+diff --git a/arch/nios2nommu/drivers/altcf.c b/arch/nios2nommu/drivers/altcf.c
+new file mode 100644
+index 0000000..80275c6
+--- /dev/null
++++ b/arch/nios2nommu/drivers/altcf.c
+@@ -0,0 +1,266 @@
++/*
++ * linux/drivers/ide/altcf.c
++ * Support for Altera CompactFlash core with Avalon interface.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/ioport.h>
++#include <linux/blkdev.h>
++#include <linux/hdreg.h>
++#include <linux/ide.h>
++#include <linux/init.h>
++#include <asm/io.h>
++#include <asm/nios.h>
++
++MODULE_AUTHOR("Microtronix Datacom Ltd.");
++MODULE_DESCRIPTION("Driver of Altera CompactFlash core with Avalon interface");
++MODULE_LICENSE("GPL");
++
++#define PDEBUG printk
++/* Altera Avalon Compact Flash core registers */
++#define REG_CFCTL 0
++#define REG_IDECTL 4
++
++/* CFCTL bits */
++#define CFCTL_DET 1 /* detect status */
++#define CFCTL_PWR 2 /* Power */
++#define CFCTL_RST 4 /* Reset */
++#define CFCTL_IDET 8 /* Detect int enable*/
++
++/* IDECTL bits */
++#define IDECTL_IIDE 1 /* IDE int enable */
++
++struct cf_dev {
++ int base;
++ int irq;
++ int ide_base;
++ int ide_irq;
++ int configured;
++ ide_hwif_t *hwif;
++ struct delayed_work wcf;
++};
++
++static struct cf_dev cf_devices[MAX_HWIFS] = {
++#if MAX_HWIFS > 0
++ {na_ide_ctl, na_ide_ctl_irq, na_ide_ide, na_ide_ide_irq, 0, NULL},
++#endif
++#if MAX_HWIFS > 1
++ {na_ctl_base1, na_ctl_irq1, na_ide_base1, na_ide_irq1, 0, NULL},
++#endif
++#if MAX_HWIFS > 2
++ {na_ctl_base2, na_ctl_irq2, na_ide_base2, na_ide_irq2, 0, NULL},
++#endif
++#if MAX_HWIFS > 3
++ {na_ctl_base3, na_ctl_irq3, na_ide_base3, na_ide_irq3, 0, NULL},
++#endif
++};
++
++static inline void cf_init_hwif_ports(hw_regs_t *hw,
++ unsigned long io_addr,
++ unsigned long ctl_addr,
++ int *irq)
++{
++ unsigned int i;
++
++ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
++ hw->io_ports[i] = io_addr + 4*(i-IDE_DATA_OFFSET);
++
++ hw->io_ports[IDE_CONTROL_OFFSET] = ctl_addr;
++
++ if (irq)
++ *irq = 0;
++
++ hw->io_ports[IDE_IRQ_OFFSET] = 0;
++
++}
++
++static int cf_release(struct cf_dev* dev)
++{
++ if (dev) {
++ if ((dev->configured) && (dev->hwif)) {
++ /* disable IDE interrupts */
++ outl(0, dev->base + REG_IDECTL);
++ /* power off the card */
++ //outl(0, dev->base + REG_CFCTL);
++
++ ide_unregister(dev->hwif->index);
++ dev->configured = 0;
++ dev->hwif = NULL;
++ PDEBUG("CF released\n");
++ return 0;
++ }
++ }
++ return -1;
++}
++
++static int cf_config(struct cf_dev* dev)
++{
++ hw_regs_t hw;
++ int index;
++ ide_hwif_t *hwif;
++
++ if (!dev)
++ return -1;
++
++ if (!dev->configured) {
++ int i;
++ for (i=1; i<=10; i++) {
++ cf_init_hwif_ports(&hw, dev->ide_base, 0, NULL);
++ hw.irq = dev->ide_irq;
++ hw.chipset = ide_generic;
++ outl(IDECTL_IIDE, dev->base + REG_IDECTL);
++ index = ide_register_hw(&hw, 1, &hwif);
++ if (index >=0) {
++ dev->configured = 1;
++ dev->hwif = hwif;
++ return index;
++ }
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(HZ/10);
++ }
++ /* register fails */
++ PDEBUG("CF:fail to register\n");
++ /* disable IDE interrupt */
++ outl(0, dev->base + REG_IDECTL);
++ return -1;
++ }
++ return -2; /* already configured */
++}
++
++static irqreturn_t cf_intr(int irq, void *dev_id)
++{
++ unsigned int cfctl;
++ struct cf_dev* dev = (struct cf_dev *)dev_id;
++
++ if (!dev)
++ return IRQ_NONE;
++
++ cfctl=inl(dev->base + REG_CFCTL);
++ /* unpower the card */
++ outl((cfctl & ~(CFCTL_PWR)), dev->base + REG_CFCTL);
++
++ if ((cfctl & CFCTL_DET))
++ schedule_delayed_work(&dev->wcf, HZ/2);
++ else
++ schedule_work(&dev->wcf.work);
++ return IRQ_HANDLED;
++}
++
++static void cf_event(struct work_struct *work)
++{
++ struct cf_dev* dev = container_of(work, struct cf_dev, wcf.work);
++
++ if (dev) {
++ unsigned int cfctl;
++
++ cfctl=inl(dev->base + REG_CFCTL);
++ if ((cfctl & CFCTL_DET)) {
++ /* a CF card is inserted, power on the card */
++ outl(((cfctl | CFCTL_PWR) & ~(CFCTL_RST) ), dev->base + REG_CFCTL);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(HZ);
++ cf_config(dev);
++ }
++ else {
++ /* a CF card is removed */
++ cf_release(dev);
++ }
++ }
++}
++
++int __init altcf_init(void)
++{
++ unsigned int cfctl;
++ int i;
++ ide_hwif_t *hwif;
++ hw_regs_t hw;
++ extern ide_hwif_t ide_hwifs[];
++
++ for (i=0; i<MAX_HWIFS; i++) {
++ cfctl=inl(cf_devices[i].base + REG_CFCTL);
++ PDEBUG("CF: ctl=%d\n", cfctl);
++ if (cfctl & CFCTL_DET)
++ {
++ /* power off the card */
++ outl(CFCTL_RST, cf_devices[i].base + REG_CFCTL);
++ mdelay(500);
++ cfctl=inl(cf_devices[i].base + REG_CFCTL);
++
++ /* power on the card */
++ outl(((cfctl | CFCTL_PWR) & ~(CFCTL_RST) ), cf_devices[i].base + REG_CFCTL);
++ mdelay(2000);
++ inl(cf_devices[i].base + REG_CFCTL);
++
++ /* check if card is in right mode */
++ outb(0xa0, cf_devices[i].ide_base+IDE_SELECT_OFFSET*4);
++ mdelay(50);
++ if (inb(cf_devices[i].ide_base+IDE_SELECT_OFFSET*4) == 0xa0) {
++ /* enable IDE interrupt */
++ outl(IDECTL_IIDE, cf_devices[i].base + REG_IDECTL);
++ ide_hwifs[i].chipset = ide_generic;
++ cf_devices[i].hwif = &ide_hwifs[i];
++
++ memset(&hw, 0, sizeof hw);
++ cf_init_hwif_ports(&hw, cf_devices[i].ide_base, 0, NULL);
++ hw.chipset = ide_generic;
++ hw.irq = cf_devices[i].ide_irq;
++ if (ide_register_hw(&hw, 1, &hwif)>=0) {
++ cf_devices[i].configured = 1;
++ cf_devices[i].hwif = hwif;
++ }
++ else
++ printk("CF register fails\n");
++ }
++ else printk("Unable to initialize compact flash card. Please re-insert\n");
++ }
++
++ /* register the detection interrupt */
++ if (request_irq(cf_devices[i].irq, cf_intr, IRQF_DISABLED, "cf", &cf_devices[i])) {
++ PDEBUG("CF: unable to get interrupt %d for detecting inf %d\n",
++ cf_devices[i].irq, i );
++ } else {
++ INIT_DELAYED_WORK(&cf_devices[i].wcf, cf_event);
++ /* enable the detection interrupt */
++ cfctl=inl(cf_devices[i].base + REG_CFCTL);
++ outl(cfctl | CFCTL_IDET, cf_devices[i].base + REG_CFCTL);
++ }
++ }
++
++ return 0;
++}
++
++#ifdef MODULE
++static void __exit altcf_exit(void)
++{
++ unsigned int cfctl;
++ for (i=0; i<MAX_HWIFS; i++) {
++ /* disable detection irq */
++ cfctl=inl(cf_devices[i].base + REG_CFCTL);
++ outl(cfctl & ~CFCTL_IDET, cf_devices[i].base + REG_CFCTL);
++
++ /* free the detection irq */
++ free_irq(cf_devices[i].irq, &cf_devices[i]);
++
++ /* release the device */
++ cf_release(&cf_devices[i]);
++ }
++}
++
++module_init(altcf_init);
++module_exit(altcf_exit);
++#endif
+diff --git a/arch/nios2nommu/drivers/altfb.c b/arch/nios2nommu/drivers/altfb.c
+new file mode 100644
+index 0000000..cebd659
+--- /dev/null
++++ b/arch/nios2nommu/drivers/altfb.c
+@@ -0,0 +1,234 @@
++/*
++ * Altera VGA controller
++ *
++ * linux/drivers/video/vfb.c -- Virtual frame buffer device
++ *
++ * Copyright (C) 2002 James Simmons
++ *
++ * Copyright (C) 1997 Geert Uytterhoeven
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++
++#include <asm/uaccess.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++
++#define vgabase na_vga_controller_0
++#define XRES 640
++#define YRES 480
++#define BPX 16
++
++ /*
++ * RAM we reserve for the frame buffer. This defines the maximum screen
++ * size
++ *
++ * The default can be overridden if the driver is compiled as a module
++ */
++
++#define VIDEOMEMSIZE (XRES * YRES * (BPX>>3))
++
++static void *videomemory;
++static u_long videomemorysize = VIDEOMEMSIZE;
++module_param(videomemorysize, ulong, 0);
++
++static struct fb_var_screeninfo altfb_default __initdata = {
++ .xres = XRES,
++ .yres = YRES,
++ .xres_virtual = XRES,
++ .yres_virtual = YRES,
++ .bits_per_pixel = BPX,
++#if (BPX == 16)
++ .red = { 11, 5, 0 },
++ .green = { 5, 6, 0 },
++ .blue = { 0, 5, 0 },
++#else // BPX == 24
++ .red = { 16, 8, 0 },
++ .green = { 8, 8, 0 },
++ .blue = { 0, 8, 0 },
++#endif
++ .activate = FB_ACTIVATE_NOW,
++ .height = -1,
++ .width = -1,
++ // timing useless ?
++ .pixclock = 20000,
++ .left_margin = 64,
++ .right_margin = 64,
++ .upper_margin = 32,
++ .lower_margin = 32,
++ .hsync_len = 64,
++ .vsync_len = 2,
++ .vmode = FB_VMODE_NONINTERLACED,
++};
++
++static struct fb_fix_screeninfo altfb_fix __initdata = {
++ .id = "Altera FB",
++ .type = FB_TYPE_PACKED_PIXELS,
++ .visual = FB_VISUAL_TRUECOLOR,
++ .line_length = (XRES * (BPX>>3)),
++ .xpanstep = 0,
++ .ypanstep = 0,
++ .ywrapstep = 0,
++ .accel = FB_ACCEL_NONE,
++};
++
++static int altfb_mmap(struct fb_info *info,
++ struct vm_area_struct *vma);
++
++static struct fb_ops altfb_ops = {
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_mmap = altfb_mmap,
++};
++
++
++ /*
++ * Most drivers don't need their own mmap function
++ */
++
++static int altfb_mmap(struct fb_info *info,
++ struct vm_area_struct *vma)
++{
++ /* this is uClinux (no MMU) specific code */
++ vma->vm_flags |= (VM_RESERVED | VM_MAYSHARE);
++ vma->vm_start = (unsigned) videomemory;
++ return 0;
++}
++
++ /*
++ * Initialisation
++ */
++
++static void altfb_platform_release(struct device *device)
++{
++ // This is called when the reference count goes to zero.
++ dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
++}
++
++static int __init altfb_probe(struct platform_device *dev)
++{
++ struct fb_info *info;
++ int retval = -ENOMEM;
++ dma_addr_t handle;
++
++ /*
++ * For real video cards we use ioremap.
++ */
++ if (!(videomemory = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(videomemorysize), &handle, GFP_KERNEL))) {
++ printk(KERN_ERR "altfb: unable to allocate screen memory\n");
++ return retval;
++ }
++ altfb_fix.smem_start = handle;
++ altfb_fix.smem_len = videomemorysize;
++
++ info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
++ if (!info)
++ goto err;
++
++ info->screen_base = (char __iomem *)videomemory;
++ info->fbops = &altfb_ops;
++ info->var = altfb_default;
++ info->fix = altfb_fix;
++ info->pseudo_palette = info->par;
++ info->par = NULL;
++ info->flags = FBINFO_FLAG_DEFAULT;
++
++ retval = fb_alloc_cmap(&info->cmap, 256, 0);
++ if (retval < 0)
++ goto err1;
++
++ retval = register_framebuffer(info);
++ if (retval < 0)
++ goto err2;
++ platform_set_drvdata(dev, info);
++
++ outl(0x0,vgabase+0); // Reset the VGA controller
++ outl(videomemory,vgabase+4); // Where our frame buffer starts
++ outl(videomemorysize,vgabase+8); // amount of memory needed
++ outl(0x1,vgabase+0); // Set the go bit
++
++ printk(KERN_INFO
++ "fb%d: Altera frame buffer device, using %ldK of video memory\n",
++ info->node, videomemorysize >> 10);
++ // printk("vga %08x, video %08x+%08x\n",vgabase,videomemory,videomemorysize);
++ return 0;
++err2:
++ fb_dealloc_cmap(&info->cmap);
++err1:
++ framebuffer_release(info);
++err:
++ dma_free_noncoherent(&dev->dev, videomemorysize, videomemory, handle);
++ return retval;
++}
++
++static int altfb_remove(struct platform_device *dev)
++{
++ struct fb_info *info = platform_get_drvdata(dev);
++
++ if (info) {
++ unregister_framebuffer(info);
++ dma_free_noncoherent(&dev->dev, videomemorysize, videomemory, altfb_fix.smem_start);
++ framebuffer_release(info);
++ }
++ return 0;
++}
++
++static struct platform_driver altfb_driver = {
++ .probe = altfb_probe,
++ .remove = altfb_remove,
++ .driver = {
++ .name = "altfb",
++ },
++};
++
++static struct platform_device altfb_device = {
++ .name = "altfb",
++ .id = 0,
++ .dev = {
++ .release = altfb_platform_release,
++ }
++};
++
++static int __init altfb_init(void)
++{
++ int ret = 0;
++
++ ret = platform_driver_register(&altfb_driver);
++
++ if (!ret) {
++ ret = platform_device_register(&altfb_device);
++ if (ret)
++ platform_driver_unregister(&altfb_driver);
++ }
++ return ret;
++}
++
++module_init(altfb_init);
++
++#ifdef MODULE
++static void __exit altfb_exit(void)
++{
++ platform_device_unregister(&altfb_device);
++ platform_driver_unregister(&altfb_driver);
++}
++
++module_exit(altfb_exit);
++
++MODULE_LICENSE("GPL");
++#endif /* MODULE */
+diff --git a/arch/nios2nommu/drivers/altps2.c b/arch/nios2nommu/drivers/altps2.c
+new file mode 100644
+index 0000000..4a6523c
+--- /dev/null
++++ b/arch/nios2nommu/drivers/altps2.c
+@@ -0,0 +1,193 @@
++/*
++ * altera DE2 PS/2
++ *
++ * linux/drivers/input/serio/sa1111ps2.c
++ *
++ * Copyright (C) 2002 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.
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/serio.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <asm/io.h>
++#include <asm/system.h>
++
++
++struct ps2if {
++ struct serio *io;
++ struct platform_device *dev;
++ unsigned base;
++ unsigned irq;
++};
++
++/*
++ * Read all bytes waiting in the PS2 port. There should be
++ * at the most one, but we loop for safety. If there was a
++ * framing error, we have to manually clear the status.
++ */
++static irqreturn_t ps2_rxint(int irq, void *dev_id)
++{
++ struct ps2if *ps2if = dev_id;
++ unsigned int status;
++ int handled = IRQ_NONE;
++
++ while ((status = inl(ps2if->base)) & 0xffff0000) {
++ serio_interrupt(ps2if->io, status & 0xff, 0);
++ handled = IRQ_HANDLED;
++ }
++ return handled;
++}
++
++/*
++ * Write a byte to the PS2 port. We have to wait for the
++ * port to indicate that the transmitter is empty.
++ */
++static int ps2_write(struct serio *io, unsigned char val)
++{
++ struct ps2if *ps2if = io->port_data;
++ outl(val,ps2if->base);
++ // should check command send error
++ if (inl(ps2if->base+4) & (1<<10))
++ {
++ // printk("ps2 write error %02x\n",val);
++ }
++ return 0;
++}
++
++static int ps2_open(struct serio *io)
++{
++ struct ps2if *ps2if = io->port_data;
++ int ret;
++
++ ret = request_irq(ps2if->irq, ps2_rxint, 0,
++ "altps2", ps2if);
++ if (ret) {
++ printk(KERN_ERR "altps2: could not allocate IRQ%d: %d\n",
++ ps2if->irq, ret);
++ return ret;
++ }
++ outl(1,ps2if->base+4); // enable rx irq
++ return 0;
++}
++
++static void ps2_close(struct serio *io)
++{
++ struct ps2if *ps2if = io->port_data;
++ outl(0,ps2if->base); // disable rx irq
++ free_irq(ps2if->irq, ps2if);
++}
++
++/*
++ * Add one device to this driver.
++ */
++static int ps2_probe(struct platform_device *dev)
++{
++ struct ps2if *ps2if;
++ struct serio *serio;
++ unsigned int status;
++ int ret;
++
++ ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
++ serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
++ if (!ps2if || !serio) {
++ ret = -ENOMEM;
++ goto free;
++ }
++
++ memset(ps2if, 0, sizeof(struct ps2if));
++ memset(serio, 0, sizeof(struct serio));
++
++ serio->id.type = SERIO_8042;
++ serio->write = ps2_write;
++ serio->open = ps2_open;
++ serio->close = ps2_close;
++ strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
++ strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
++ serio->port_data = ps2if;
++ serio->dev.parent = &dev->dev;
++ ps2if->io = serio;
++ ps2if->dev = dev;
++ platform_set_drvdata(dev, ps2if);
++
++ /*
++ * Request the physical region for this PS2 port.
++ */
++ if (dev->num_resources < 2) {
++ ret = -ENODEV;
++ goto out;
++ }
++ if (!request_mem_region(dev->resource[0].start,
++ 4,
++ "altps2")) {
++ ret = -EBUSY;
++ goto free;
++ }
++ ps2if->base = dev->resource[0].start;
++ ps2if->irq = dev->resource[1].start;
++ printk("altps2 : base %08x irq %d\n",ps2if->base,ps2if->irq);
++ // clear fifo
++ while ((status = inl(ps2if->base)) & 0xffff0000) {
++ }
++
++ serio_register_port(ps2if->io);
++ return 0;
++
++ out:
++ release_mem_region(dev->resource[0].start,4);
++ free:
++ platform_set_drvdata(dev, NULL);
++ kfree(ps2if);
++ kfree(serio);
++ return ret;
++}
++
++/*
++ * Remove one device from this driver.
++ */
++static int ps2_remove(struct platform_device *dev)
++{
++ struct ps2if *ps2if = platform_get_drvdata(dev);
++
++ platform_set_drvdata(dev, NULL);
++ serio_unregister_port(ps2if->io);
++ release_mem_region(dev->resource[0].start,4);
++
++ kfree(ps2if);
++
++ return 0;
++}
++
++/*
++ * Our device driver structure
++ */
++static struct platform_driver ps2_driver = {
++ .probe = ps2_probe,
++ .remove = ps2_remove,
++ .driver = {
++ .name = "altps2",
++ },
++};
++
++static int __init ps2_init(void)
++{
++ return platform_driver_register(&ps2_driver);
++}
++
++static void __exit ps2_exit(void)
++{
++ platform_driver_unregister(&ps2_driver);
++}
++
++module_init(ps2_init);
++module_exit(ps2_exit);
+diff --git a/arch/nios2nommu/drivers/i2c-gpio.c b/arch/nios2nommu/drivers/i2c-gpio.c
+new file mode 100644
+index 0000000..3f5e51a
+--- /dev/null
++++ b/arch/nios2nommu/drivers/i2c-gpio.c
+@@ -0,0 +1,166 @@
++/*
++ * drivers/i2c/busses/i2c-gpio.c for Nios2
++ *
++ * drivers/i2c/busses/i2c-ixp2000.c
++ *
++ * I2C adapter for IXP2000 systems using GPIOs for I2C bus
++ *
++ * Author: Deepak Saxena <dsaxena@plexity.net>
++ * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com>
++ * Made generic by: Jeff Daly <jeffrey.daly@intel.com>
++ *
++ * Copyright (c) 2003-2004 MontaVista Software Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ * From Jeff Daly:
++ *
++ * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any
++ * IXP2000 platform if it uses the HW GPIO in the same manner. Basically,
++ * SDA and SCL GPIOs have external pullups. Setting the respective GPIO to
++ * an input will make the signal a '1' via the pullup. Setting them to
++ * outputs will pull them down.
++ *
++ * The GPIOs are open drain signals and are used as configuration strap inputs
++ * during power-up so there's generally a buffer on the board that needs to be
++ * 'enabled' to drive the GPIOs.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <linux/i2c-id.h>
++
++#include <asm/io.h>
++#include <asm/gpio.h>
++
++static inline int gpio_scl_pin(void *data)
++{
++ return ((struct gpio_i2c_pins*)data)->scl_pin;
++}
++
++static inline int gpio_sda_pin(void *data)
++{
++ return ((struct gpio_i2c_pins*)data)->sda_pin;
++}
++
++
++static void gpio_bit_setscl(void *data, int val)
++{
++ int i = 5000;
++
++ if (val) {
++ outl(3,gpio_scl_pin(data));
++ while(!(inl(gpio_scl_pin(data)) & 1) && i--);
++ } else {
++ outl(2,gpio_scl_pin(data));
++ }
++}
++
++static void gpio_bit_setsda(void *data, int val)
++{
++ if (val) {
++ outl(1,gpio_sda_pin(data));
++ } else {
++ outl(0,gpio_sda_pin(data));
++ }
++}
++
++static int gpio_bit_getscl(void *data)
++{
++ return inl(gpio_scl_pin(data)) & 1;
++}
++
++static int gpio_bit_getsda(void *data)
++{
++ return inl(gpio_sda_pin(data)) & 1;
++}
++
++struct gpio_i2c_data {
++ struct gpio_i2c_pins *gpio_pins;
++ struct i2c_adapter adapter;
++ struct i2c_algo_bit_data algo_data;
++};
++
++static int gpio_i2c_remove(struct platform_device *plat_dev)
++{
++ struct gpio_i2c_data *drv_data = platform_get_drvdata(plat_dev);
++
++ platform_set_drvdata(plat_dev, NULL);
++
++ i2c_del_adapter(&drv_data->adapter);
++
++ kfree(drv_data);
++
++ return 0;
++}
++
++static int gpio_i2c_probe(struct platform_device *plat_dev)
++{
++ int err;
++ struct gpio_i2c_pins *gpio = plat_dev->dev.platform_data;
++ struct gpio_i2c_data *drv_data =
++ kzalloc(sizeof(struct gpio_i2c_data), GFP_KERNEL);
++
++ if (!drv_data)
++ return -ENOMEM;
++ drv_data->gpio_pins = gpio;
++
++ drv_data->algo_data.data = gpio;
++ drv_data->algo_data.setsda = gpio_bit_setsda;
++ drv_data->algo_data.setscl = gpio_bit_setscl;
++ drv_data->algo_data.getsda = gpio_bit_getsda;
++ drv_data->algo_data.getscl = gpio_bit_getscl;
++ drv_data->algo_data.udelay = 6;
++ drv_data->algo_data.timeout = 100;
++
++ drv_data->adapter.id = I2C_HW_B_IXP2000, // borrowed,
++ strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
++ I2C_NAME_SIZE);
++ drv_data->adapter.algo_data = &drv_data->algo_data,
++
++ drv_data->adapter.dev.parent = &plat_dev->dev;
++ drv_data->adapter.class = I2C_CLASS_ALL;
++
++ outl(1,gpio->sda_pin);
++ outl(1,gpio->scl_pin);
++
++ if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {
++ dev_err(&plat_dev->dev, "Could not install, error %d\n", err);
++ kfree(drv_data);
++ return err;
++ }
++
++ platform_set_drvdata(plat_dev, drv_data);
++ printk("i2c-gpio driver at %08x\n",gpio->sda_pin);
++
++ return 0;
++}
++
++static struct platform_driver gpio_i2c_driver = {
++ .probe = gpio_i2c_probe,
++ .remove = gpio_i2c_remove,
++ .driver = {
++ .name = "GPIO-I2C",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init gpio_i2c_init(void)
++{
++ return platform_driver_register(&gpio_i2c_driver);
++}
++
++static void __exit gpio_i2c_exit(void)
++{
++ platform_driver_unregister(&gpio_i2c_driver);
++}
++
++module_init(gpio_i2c_init);
++module_exit(gpio_i2c_exit);
++
+diff --git a/arch/nios2nommu/drivers/pci/Kconfig b/arch/nios2nommu/drivers/pci/Kconfig
+new file mode 100644
+index 0000000..6c3b175
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/Kconfig
+@@ -0,0 +1,4 @@
++config PCI_ALTPCI
++ bool "Altera PCI host bridge"
++ select PCI
++ default n
+diff --git a/arch/nios2nommu/drivers/pci/Makefile b/arch/nios2nommu/drivers/pci/Makefile
+new file mode 100644
+index 0000000..b027e1e
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/Makefile
+@@ -0,0 +1,6 @@
++#
++# Makefile for the PCI specific kernel interface routines under Linux.
++#
++
++obj-y += pci.o
++obj-$(CONFIG_PCI_ALTPCI) += altpci.o setup-irq.o pci-auto.o
+diff --git a/arch/nios2nommu/drivers/pci/altpci.c b/arch/nios2nommu/drivers/pci/altpci.c
+new file mode 100644
+index 0000000..85959ea
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/altpci.c
+@@ -0,0 +1,204 @@
++/* arch/sh/kernel/pci.c
++ * $Id: altpci.c,v 1.1 2006/07/05 06:23:17 gerg Exp $
++ *
++ * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
++ *
++ *
++ * These functions are collected here to reduce duplication of common
++ * code amongst the many platform-specific PCI support code files.
++ *
++ * These routines require the following board-specific routines:
++ * void pcibios_fixup_irqs();
++ *
++ * See include/asm-sh/pci.h for more information.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++
++/*
++ * Direct access to PCI hardware...
++ */
++#define pcicfg_space (na_pci_compiler_0_PCI_Bus_Access) // avalon space
++#define pciio (pcicfg_space+0x100000) // pci io device base in avalon space
++#define pcimm (pcicfg_space+0x200000) // pci mem device base in avalon space
++ // idsel of ad11=dev0,ad12=dev1 , using type 0 config request
++#define pcicfg(dev,fun,reg) (pcicfg_space | ((dev)<<11) | ((fun)<<8) | (reg)) // cfg space
++
++// FIX ME for your board, dram device for external pci masters access
++static int __init alt_pci_init(void)
++{
++ unsigned dev,fun;
++ // setup dram bar
++ dev=0; fun=0;
++ outl(nasys_program_mem,pcicfg(dev,fun,0x10)); // mem space
++ outw(0x0006,pcicfg(dev,fun,0x04)); // enable master, mem space
++ return 0;
++}
++
++subsys_initcall(alt_pci_init);
++
++#define PCICFG(bus, devfn, where) (pcicfg_space | (bus->number << 16) | (devfn << 8) | (where & ~3))
++#define ALT_PCI_IO_BASE (pciio)
++#define ALT_PCI_IO_SIZE 0x100000
++#define ALT_PCI_MEMORY_BASE (pcimm)
++#define ALT_PCI_MEM_SIZE 0x100000
++
++/*
++ * Functions for accessing PCI configuration space with type 1 accesses
++ */
++
++// FIX ME for your board, number of pci bus, and number of devices
++static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn)
++{
++ if (bus->number > 0 || PCI_SLOT(devfn) == 0 || PCI_SLOT(devfn) > 2)
++ return -1;
++
++ return 0;
++}
++
++static int alt_pci_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 *val)
++{
++ u32 data;
++
++ if (pci_range_ck(bus, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ // local_irq_save(flags);
++ data = inl(PCICFG(bus, devfn, where));
++ // local_irq_restore(flags);
++
++ switch (size) {
++ case 1:
++ *val = (data >> ((where & 3) << 3)) & 0xff;
++ break;
++ case 2:
++ *val = (data >> ((where & 2) << 3)) & 0xffff;
++ break;
++ case 4:
++ *val = data;
++ break;
++ default:
++ return PCIBIOS_FUNC_NOT_SUPPORTED;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++/*
++ * we'll do a read,
++ * mask,write operation.
++ * We'll allow an odd byte offset, though it should be illegal.
++ */
++static int alt_pci_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ int shift;
++ u32 data;
++
++ if (pci_range_ck(bus, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ // local_irq_save(flags);
++ data = inl(PCICFG(bus, devfn, where));
++ // local_irq_restore(flags);
++
++ switch (size) {
++ case 1:
++ shift = (where & 3) << 3;
++ data &= ~(0xff << shift);
++ data |= ((val & 0xff) << shift);
++ break;
++ case 2:
++ shift = (where & 2) << 3;
++ data &= ~(0xffff << shift);
++ data |= ((val & 0xffff) << shift);
++ break;
++ case 4:
++ data = val;
++ break;
++ default:
++ return PCIBIOS_FUNC_NOT_SUPPORTED;
++ }
++
++ outl(data, PCICFG(bus, devfn, where));
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++struct pci_ops alt_pci_ops = {
++ .read = alt_pci_read,
++ .write = alt_pci_write,
++};
++
++static struct resource alt_io_resource = {
++ .name = "ALTPCI IO",
++ .start = ALT_PCI_IO_BASE,
++ .end = ALT_PCI_IO_BASE + ALT_PCI_IO_SIZE - 1,
++ .flags = IORESOURCE_IO
++};
++
++static struct resource alt_mem_resource = {
++ .name = "ALTPCI mem",
++ .start = ALT_PCI_MEMORY_BASE,
++ .end = ALT_PCI_MEMORY_BASE + ALT_PCI_MEM_SIZE - 1,
++ .flags = IORESOURCE_MEM
++};
++
++extern struct pci_ops alt_pci_ops;
++
++struct pci_channel board_pci_channels[] = {
++ { &alt_pci_ops, &alt_io_resource, &alt_mem_resource, 0, 0xff },
++ { NULL, NULL, NULL, 0, 0 },
++};
++
++char *pcibios_setup(char *option)
++{
++ /* Nothing for us to handle. */
++ return(option);
++}
++
++void pcibios_fixup_bus(struct pci_bus *b)
++{
++}
++
++/*
++ * IRQ functions
++ */
++static u8 __init altpci_no_swizzle(struct pci_dev *dev, u8 *pin)
++{
++ /* no swizzling */
++ return PCI_SLOT(dev->devfn);
++}
++
++// FIX ME for your board, nios2 irqn mapping
++int __init pcibios_map_platform_irq(u8 slot, u8 pin)
++{
++ int irq = na_irqn_0_irq + ((slot-1)*4) + (pin-1);
++ // printk("map slot %d pin %d irq %d\n",slot,pin,irq);
++ return irq;
++}
++
++static int altpci_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq = -1;
++
++ /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
++ irq = pcibios_map_platform_irq(slot,pin);
++ if( irq < 0 ) {
++ // printk("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
++ return irq;
++ }
++
++ // printk("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
++
++ return irq;
++}
++
++void __init pcibios_fixup_irqs(void)
++{
++ pci_fixup_irqs(altpci_no_swizzle, altpci_pci_lookup_irq);
++}
++
+diff --git a/arch/nios2nommu/drivers/pci/pci-auto.c b/arch/nios2nommu/drivers/pci/pci-auto.c
+new file mode 100644
+index 0000000..e1cdfdc
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/pci-auto.c
+@@ -0,0 +1,559 @@
++/*
++ * PCI autoconfiguration library
++ *
++ * Author: Matt Porter <mporter@mvista.com>
++ *
++ * Copyright 2000, 2001 MontaVista Software Inc.
++ * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
++ * Copyright 2003 Paul Mundt <lethal@linux-sh.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++/*
++ * Modified for MIPS by Jun Sun, jsun@mvista.com
++ *
++ * . Simplify the interface between pci_auto and the rest: a single function.
++ * . Assign resources from low address to upper address.
++ * . change most int to u32.
++ *
++ * Further modified to include it as mips generic code, ppopov@mvista.com.
++ *
++ * 2001-10-26 Bradley D. LaRonde <brad@ltc.com>
++ * - Add a top_bus argument to the "early config" functions so that
++ * they can set a fake parent bus pointer to convince the underlying
++ * pci ops to use type 1 configuration for sub busses.
++ * - Set bridge base and limit registers correctly.
++ * - Align io and memory base properly before and after bridge setup.
++ * - Don't fall through to pci_setup_bars for bridge.
++ * - Reformat the debug output to look more like lspci's output.
++ *
++ * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org
++ *
++ * 2003-08-05 Paul Mundt <lethal@linux-sh.org>
++ * - Don't update the BAR values on systems that already have valid addresses
++ * and don't want these updated for whatever reason, by way of a new config
++ * option check. However, we still read in the old BAR values so that they
++ * can still be reported through the debug output.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++
++#undef DEBUG
++#define DEBUG // you can remove debug message here
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++/*
++ * These functions are used early on before PCI scanning is done
++ * and all of the pci_dev and pci_bus structures have been created.
++ */
++static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
++ int top_bus, int busnr, int devfn)
++{
++ static struct pci_dev dev;
++ static struct pci_bus bus;
++
++ dev.bus = &bus;
++ dev.sysdata = hose;
++ dev.devfn = devfn;
++ bus.number = busnr;
++ bus.ops = hose->pci_ops;
++
++ if(busnr != top_bus)
++ /* Fake a parent bus structure. */
++ bus.parent = &bus;
++ else
++ bus.parent = NULL;
++
++ return &dev;
++}
++
++#define EARLY_PCI_OP(rw, size, type) \
++int early_##rw##_config_##size(struct pci_channel *hose, \
++ int top_bus, int bus, int devfn, int offset, type value) \
++{ \
++ return pci_##rw##_config_##size( \
++ fake_pci_dev(hose, top_bus, bus, devfn), \
++ offset, value); \
++}
++
++EARLY_PCI_OP(read, byte, u8 *)
++EARLY_PCI_OP(read, word, u16 *)
++EARLY_PCI_OP(read, dword, u32 *)
++EARLY_PCI_OP(write, byte, u8)
++EARLY_PCI_OP(write, word, u16)
++EARLY_PCI_OP(write, dword, u32)
++
++static struct resource *io_resource_inuse;
++static struct resource *mem_resource_inuse;
++
++static u32 pciauto_lower_iospc;
++static u32 pciauto_upper_iospc;
++
++static u32 pciauto_lower_memspc;
++static u32 pciauto_upper_memspc;
++
++static void __init
++pciauto_setup_bars(struct pci_channel *hose,
++ int top_bus,
++ int current_bus,
++ int pci_devfn,
++ int bar_limit)
++{
++ u32 bar_response, bar_size, bar_value;
++ u32 bar, addr_mask, bar_nr = 0;
++ u32 * upper_limit;
++ u32 * lower_limit;
++ int found_mem64 = 0;
++
++ for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
++#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
++ u32 bar_addr;
++
++ /* Read the old BAR value */
++ early_read_config_dword(hose, top_bus,
++ current_bus,
++ pci_devfn,
++ bar,
++ &bar_addr);
++#endif
++
++ /* Tickle the BAR and get the response */
++ early_write_config_dword(hose, top_bus,
++ current_bus,
++ pci_devfn,
++ bar,
++ 0xffffffff);
++
++ early_read_config_dword(hose, top_bus,
++ current_bus,
++ pci_devfn,
++ bar,
++ &bar_response);
++
++#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
++ /*
++ * Write the old BAR value back out, only update the BAR
++ * if we implicitly want resources to be updated, which
++ * is done by the generic code further down. -- PFM.
++ */
++ early_write_config_dword(hose, top_bus,
++ current_bus,
++ pci_devfn,
++ bar,
++ bar_addr);
++#endif
++
++ /* If BAR is not implemented go to the next BAR */
++ if (!bar_response)
++ continue;
++
++ /*
++ * Workaround for a BAR that doesn't use its upper word,
++ * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
++ * bdl <brad@ltc.com>
++ */
++ if (!(bar_response & 0xffff0000))
++ bar_response |= 0xffff0000;
++
++retry:
++ /* Check the BAR type and set our address mask */
++ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
++ addr_mask = PCI_BASE_ADDRESS_IO_MASK;
++ upper_limit = &pciauto_upper_iospc;
++ lower_limit = &pciauto_lower_iospc;
++ DBG(" I/O");
++ } else {
++ if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
++ PCI_BASE_ADDRESS_MEM_TYPE_64)
++ found_mem64 = 1;
++
++ addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
++ upper_limit = &pciauto_upper_memspc;
++ lower_limit = &pciauto_lower_memspc;
++ DBG(" Mem");
++ }
++
++
++ /* Calculate requested size */
++ bar_size = ~(bar_response & addr_mask) + 1;
++
++ /* Allocate a base address */
++ bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
++
++ if ((bar_value + bar_size) > *upper_limit) {
++ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
++ if (io_resource_inuse->child) {
++ io_resource_inuse =
++ io_resource_inuse->child;
++ pciauto_lower_iospc =
++ io_resource_inuse->start;
++ pciauto_upper_iospc =
++ io_resource_inuse->end + 1;
++ goto retry;
++ }
++
++ } else {
++ if (mem_resource_inuse->child) {
++ mem_resource_inuse =
++ mem_resource_inuse->child;
++ pciauto_lower_memspc =
++ mem_resource_inuse->start;
++ pciauto_upper_memspc =
++ mem_resource_inuse->end + 1;
++ goto retry;
++ }
++ }
++ DBG(" unavailable -- skipping, value %x size %x\n",
++ bar_value, bar_size);
++ continue;
++ }
++
++#if 1
++ /* Write it out and update our limit */
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ bar, bar_value);
++#endif
++
++ *lower_limit = bar_value + bar_size;
++
++ /*
++ * If we are a 64-bit decoder then increment to the
++ * upper 32 bits of the bar and force it to locate
++ * in the lower 4GB of memory.
++ */
++ if (found_mem64) {
++ bar += 4;
++ early_write_config_dword(hose, top_bus,
++ current_bus,
++ pci_devfn,
++ bar,
++ 0x00000000);
++ }
++
++ DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
++
++ bar_nr++;
++ }
++
++}
++
++static void __init
++pciauto_prescan_setup_bridge(struct pci_channel *hose,
++ int top_bus,
++ int current_bus,
++ int pci_devfn,
++ int sub_bus)
++{
++ /* Configure bus number registers */
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_PRIMARY_BUS, current_bus);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SECONDARY_BUS, sub_bus + 1);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SUBORDINATE_BUS, 0xff);
++
++ /* Align memory and I/O to 1MB and 4KB boundaries. */
++ pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
++ & ~(0x100000 - 1);
++ pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
++ & ~(0x1000 - 1);
++
++ /* Set base (lower limit) of address range behind bridge. */
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
++
++ /* We don't support prefetchable memory for now, so disable */
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_PREF_MEMORY_BASE, 0);
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_PREF_MEMORY_LIMIT, 0);
++}
++
++static void __init
++pciauto_postscan_setup_bridge(struct pci_channel *hose,
++ int top_bus,
++ int current_bus,
++ int pci_devfn,
++ int sub_bus)
++{
++ u32 temp;
++
++ /*
++ * [jsun] we always bump up baselines a little, so that if there
++ * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
++ * spaces.
++ */
++ pciauto_lower_memspc += 1;
++ pciauto_lower_iospc += 1;
++
++ /* Configure bus number registers */
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SUBORDINATE_BUS, sub_bus);
++
++ /* Set upper limit of address range behind bridge. */
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
++ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
++
++ /* Align memory and I/O to 1MB and 4KB boundaries. */
++ pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
++ & ~(0x100000 - 1);
++ pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
++ & ~(0x1000 - 1);
++
++ /* Enable memory and I/O accesses, enable bus master */
++ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, &temp);
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
++ | PCI_COMMAND_MASTER);
++}
++
++static void __init
++pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
++ int top_bus,
++ int current_bus,
++ int pci_devfn,
++ int sub_bus)
++{
++ /* Configure bus number registers */
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_PRIMARY_BUS, current_bus);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SECONDARY_BUS, sub_bus + 1);
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SUBORDINATE_BUS, 0xff);
++
++ /* Align memory and I/O to 4KB and 4 byte boundaries. */
++ pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
++ & ~(0x1000 - 1);
++ pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
++ & ~(0x4 - 1);
++
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_CB_IO_BASE_0, pciauto_lower_iospc);
++}
++
++static void __init
++pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
++ int top_bus,
++ int current_bus,
++ int pci_devfn,
++ int sub_bus)
++{
++ u32 temp;
++
++#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
++ /*
++ * [jsun] we always bump up baselines a little, so that if there
++ * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
++ * spaces.
++ */
++ pciauto_lower_memspc += 1;
++ pciauto_lower_iospc += 1;
++#endif
++
++ /*
++ * Configure subordinate bus number. The PCI subsystem
++ * bus scan will renumber buses (reserving three additional
++ * for this PCI<->CardBus bridge for the case where a CardBus
++ * adapter contains a P2P or CB2CB bridge.
++ */
++
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_SUBORDINATE_BUS, sub_bus);
++
++ /*
++ * Reserve an additional 4MB for mem space and 16KB for
++ * I/O space. This should cover any additional space
++ * requirement of unusual CardBus devices with
++ * additional bridges that can consume more address space.
++ *
++ * Although pcmcia-cs currently will reprogram bridge
++ * windows, the goal is to add an option to leave them
++ * alone and use the bridge window ranges as the regions
++ * that are searched for free resources upon hot-insertion
++ * of a device. This will allow a PCI<->CardBus bridge
++ * configured by this routine to happily live behind a
++ * P2P bridge in a system.
++ */
++#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
++ pciauto_lower_memspc += 0x00400000;
++ pciauto_lower_iospc += 0x00004000;
++#endif
++
++ /* Align memory and I/O to 4KB and 4 byte boundaries. */
++ pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
++ & ~(0x1000 - 1);
++ pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
++ & ~(0x4 - 1);
++ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1);
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
++
++ /* Enable memory and I/O accesses, enable bus master */
++ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, &temp);
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER);
++}
++
++#define PCIAUTO_IDE_MODE_MASK 0x05
++
++static int __init
++pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
++{
++ int sub_bus;
++ u32 pci_devfn, pci_class, cmdstat, found_multi=0;
++ unsigned short vid, did;
++ unsigned char header_type;
++ int devfn_start = 0;
++ int devfn_stop = 0xff;
++
++ sub_bus = current_bus;
++
++ if (hose->first_devfn)
++ devfn_start = hose->first_devfn;
++ if (hose->last_devfn)
++ devfn_stop = hose->last_devfn;
++
++ for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
++
++ if (PCI_FUNC(pci_devfn) && !found_multi)
++ continue;
++
++ early_read_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_VENDOR_ID, &vid);
++
++ if (vid == 0xffff) continue;
++
++ early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_HEADER_TYPE, &header_type);
++
++ if (!PCI_FUNC(pci_devfn))
++ found_multi = header_type & 0x80;
++
++ early_read_config_word(hose, top_bus, current_bus, pci_devfn,
++ PCI_DEVICE_ID, &did);
++
++ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_CLASS_REVISION, &pci_class);
++
++ if ((pci_class & 0xff000000)==0) continue; // devices before pci 2.0
++
++ DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
++ current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
++ pci_class >> 16, vid, did);
++ if (pci_class & 0xff)
++ DBG(" (rev %.2x)", pci_class & 0xff);
++ DBG("\n");
++
++ if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
++ DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
++ current_bus, sub_bus + 1);
++#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
++ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
++#endif
++ pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
++ pci_devfn, sub_bus);
++ DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
++ sub_bus + 1,
++ pciauto_lower_iospc, pciauto_lower_memspc);
++ sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
++ DBG("Back to bus %.2x\n", current_bus);
++ pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
++ pci_devfn, sub_bus);
++ continue;
++ } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
++ DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n",
++ current_bus, sub_bus + 1);
++ DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
++ /* Place CardBus Socket/ExCA registers */
++ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
++
++ pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
++ current_bus, pci_devfn, sub_bus);
++
++ DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
++ sub_bus + 1,
++ pciauto_lower_iospc, pciauto_lower_memspc);
++ sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
++ DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
++ pciauto_postscan_setup_cardbus_bridge(hose, top_bus,
++ current_bus, pci_devfn, sub_bus);
++ continue;
++ } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
++
++ unsigned char prg_iface;
++
++ early_read_config_byte(hose, top_bus, current_bus,
++ pci_devfn, PCI_CLASS_PROG, &prg_iface);
++ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
++ DBG("Skipping legacy mode IDE controller\n");
++ continue;
++ }
++ }
++
++ /*
++ * Found a peripheral, enable some standard
++ * settings
++ */
++ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, &cmdstat);
++ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
++ PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER);
++#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
++ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
++ PCI_LATENCY_TIMER, 0x80);
++#endif
++
++ /* Allocate PCI I/O and/or memory space */
++ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
++ }
++ return sub_bus;
++}
++
++int __init
++pciauto_assign_resources(int busno, struct pci_channel *hose)
++{
++ /* setup resource limits */
++ io_resource_inuse = hose->io_resource;
++ mem_resource_inuse = hose->mem_resource;
++
++ pciauto_lower_iospc = io_resource_inuse->start;
++ pciauto_upper_iospc = io_resource_inuse->end + 1;
++ pciauto_lower_memspc = mem_resource_inuse->start;
++ pciauto_upper_memspc = mem_resource_inuse->end + 1;
++ DBG("Autoconfig PCI channel 0x%p\n", hose);
++ DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
++ busno, pciauto_lower_iospc, pciauto_upper_iospc,
++ pciauto_lower_memspc, pciauto_upper_memspc);
++
++ return pciauto_bus_scan(hose, busno, busno);
++}
+diff --git a/arch/nios2nommu/drivers/pci/pci.c b/arch/nios2nommu/drivers/pci/pci.c
+new file mode 100644
+index 0000000..83436df
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/pci.c
+@@ -0,0 +1,151 @@
++/* arch/sh/kernel/pci.c
++ * $Id: pci.c,v 1.2 2007/01/25 01:26:48 gerg Exp $
++ *
++ * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
++ *
++ *
++ * These functions are collected here to reduce duplication of common
++ * code amongst the many platform-specific PCI support code files.
++ *
++ * These routines require the following board-specific routines:
++ * void pcibios_fixup_irqs();
++ *
++ * See include/asm-sh/pci.h for more information.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++
++static int __init pcibios_init(void)
++{
++ struct pci_channel *p;
++ struct pci_bus *bus;
++ int busno;
++
++#if 1
++ /* assign resources */
++ busno = 0;
++ for (p = board_pci_channels; p->pci_ops != NULL; p++) {
++ busno = pciauto_assign_resources(busno, p) + 1;
++ }
++#endif
++
++ /* scan the buses */
++ busno = 0;
++ for (p= board_pci_channels; p->pci_ops != NULL; p++) {
++ bus = pci_scan_bus(busno, p->pci_ops, p);
++ busno = bus->subordinate+1;
++ }
++
++ /* board-specific fixups */
++ pcibios_fixup_irqs();
++
++ return 0;
++}
++
++subsys_initcall(pcibios_init);
++
++void
++pcibios_update_resource(struct pci_dev *dev, struct resource *root,
++ struct resource *res, int resource)
++{
++ u32 new, check;
++ int reg;
++
++ new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
++ if (resource < 6) {
++ reg = PCI_BASE_ADDRESS_0 + 4*resource;
++ } else if (resource == PCI_ROM_RESOURCE) {
++ res->flags |= IORESOURCE_ROM_ENABLE;
++ new |= PCI_ROM_ADDRESS_ENABLE;
++ reg = dev->rom_base_reg;
++ } else {
++ /* Somebody might have asked allocation of a non-standard resource */
++ return;
++ }
++
++ pci_write_config_dword(dev, reg, new);
++ pci_read_config_dword(dev, reg, &check);
++ if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
++ printk(KERN_ERR "PCI: Error while updating region "
++ "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
++ new, check);
++ }
++}
++
++/*
++ * We need to avoid collisions with `mirrored' VGA ports
++ * and other strange ISA hardware, so we always want the
++ * addresses to be allocated in the 0x000-0x0ff region
++ * modulo 0x400.
++ */
++void pcibios_align_resource(void *data, struct resource *res,
++ resource_size_t size, resource_size_t align)
++{
++ if (res->flags & IORESOURCE_IO) {
++ unsigned long start = res->start;
++
++ if (start & 0x300) {
++ start = (start + 0x3ff) & ~0x3ff;
++ res->start = start;
++ }
++ }
++}
++
++int pcibios_enable_device(struct pci_dev *dev, int mask)
++{
++ u16 cmd, old_cmd;
++ int idx;
++ struct resource *r;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
++ for(idx=0; idx<6; idx++) {
++ if (!(mask & (1 << idx)))
++ continue;
++ r = &dev->resource[idx];
++ if (!r->start && r->end) {
++ printk(KERN_ERR "PCI: Device %s not available because "
++ "of resource collisions\n", pci_name(dev));
++ return -EINVAL;
++ }
++ if (r->flags & IORESOURCE_IO)
++ cmd |= PCI_COMMAND_IO;
++ if (r->flags & IORESOURCE_MEM)
++ cmd |= PCI_COMMAND_MEMORY;
++ }
++ if (dev->resource[PCI_ROM_RESOURCE].start)
++ cmd |= PCI_COMMAND_MEMORY;
++ if (cmd != old_cmd) {
++ printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
++ pci_name(dev), old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
++ return 0;
++}
++
++/*
++ * If we set up a device for bus mastering, we need to check and set
++ * the latency timer as it may not be properly set.
++ */
++unsigned int pcibios_max_latency = 255;
++
++void pcibios_set_master(struct pci_dev *dev)
++{
++ u8 lat;
++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
++ if (lat < 16)
++ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
++ else if (lat > pcibios_max_latency)
++ lat = pcibios_max_latency;
++ else
++ return;
++ printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
++}
++
++void __init pcibios_update_irq(struct pci_dev *dev, int irq)
++{
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
++}
+diff --git a/arch/nios2nommu/drivers/pci/setup-irq.c b/arch/nios2nommu/drivers/pci/setup-irq.c
+new file mode 100644
+index 0000000..0fa8f98
+--- /dev/null
++++ b/arch/nios2nommu/drivers/pci/setup-irq.c
+@@ -0,0 +1 @@
++#include "../../../../drivers/pci/setup-irq.c"
+diff --git a/arch/nios2nommu/drivers/spi.c b/arch/nios2nommu/drivers/spi.c
+new file mode 100644
+index 0000000..72a2519
+--- /dev/null
++++ b/arch/nios2nommu/drivers/spi.c
+@@ -0,0 +1,315 @@
++#ifdef MODULE
++#include <linux/module.h>
++#include <linux/version.h>
++#else
++#define MOD_INC_USE_COUNT
++#define MOD_DEC_USE_COUNT
++#endif
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/major.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/fcntl.h>
++#include <linux/unistd.h>
++#include <linux/init.h>
++
++
++#include <asm/io.h>
++#include <asm/segment.h>
++#include <asm/system.h>
++#include <asm/spi.h>
++
++#if !defined(SEEK_SET)
++#define SEEK_SET 0
++#endif
++
++
++static unsigned int spi_major = 60; /* a local major, can be overwritten */
++static int openflag = 0;
++static np_spi * const spi_ptr = na_spi;
++
++ /*******************************/
++ /* SPI data transfer routines. */
++ /*******************************/
++
++#define SPI_XMIT_READY np_spistatus_trdy_mask
++#define SPI_RECV_READY np_spistatus_rrdy_mask
++
++#define SPI_BUSYPOLL_TIMEOUT 1000
++
++// returns -1 if there is no data present, otherwise returns
++// the value
++inline int SPI_Recv_Byte(char *pdata )
++{
++ if (spi_ptr->np_spistatus & SPI_RECV_READY){
++ *pdata = spi_ptr->np_spirxdata & 0xff;
++ return 0;
++ }
++ return -1;
++}
++
++
++// Sends the 16 bit address+data
++inline int SPI_Send_Byte( unsigned char address, char data )
++{
++ u16 value = ((address & 0xFF) << 8) | (data & 0xFF);
++
++ if ( spi_ptr->np_spistatus & SPI_XMIT_READY ) {
++ spi_ptr->np_spitxdata = value;
++ return 0;
++ }
++
++ return -1;
++}
++
++
++
++ /*************************/
++ /* SPI Driver functions. */
++ /*************************/
++
++int spi_reset( void )
++{
++ // Nothing to do: The Nios does _not_
++ // support burst xfers. Chip Enables
++ // (Selects) are inactive after each xfer.
++ return 0;
++}
++
++
++/***************************************************/
++/* The SPI Write routine. The first 16 bits are */
++/* the device register, and the rest of the buffer */
++/* is data. */
++/***************************************************/
++
++ssize_t spi_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
++{
++ int i;
++ unsigned char addr;
++ int timeout;
++ char temp;
++
++ if ( count < 3 )
++ return -EINVAL; /* Address is 2 bytes: Must have _something_ to send */
++
++ addr = buf[0]; /* chip register address. */
++ spi_ptr->np_spistatus=0;
++
++ for ( i = sizeof(u16); i<count; i++ )
++ {
++ timeout=SPI_BUSYPOLL_TIMEOUT;
++ while (SPI_Send_Byte(addr, buf[i])==-1)
++ {
++ if (--timeout==0)
++ {
++ printk("spi_write time out\n");
++ return i; /* return the number of bytes sent */
++ }
++ }
++ /* read the data */
++ timeout=SPI_BUSYPOLL_TIMEOUT;
++ while (SPI_Recv_Byte(&temp)==-1)
++ {
++ if (--timeout==0)
++ break;
++ }
++ }
++ return i;
++// unsigned char *temp; /* Our pointer to the buffer */
++// int i;
++// int addr;
++//
++// if ( count < 3 )
++// return -EINVAL; /* Address is 2 bytes: Must have _something_ to send */
++//
++// temp = (char *)buf;
++// addr = (int)*((u16 *)temp); /* chip register address. */
++// temp += sizeof(u16);
++//
++// for ( i = count - sizeof(u16); i; i--, temp++ )
++// *temp = (unsigned char)SPI_Transfer( addr, (int)*temp );
++//
++//
++// return count; /* we can always send all data */
++}
++
++//int spi_read( struct inode *inode, struct file *file, char *buf, int count )
++ssize_t spi_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
++{
++ int i;
++ unsigned char addr;
++ int timeout;
++ char temp;
++
++ if ( count < 3 )
++ return -EINVAL; /* Address is 2 bytes: Must have _something_ to send */
++
++ addr = buf[0]; /* chip register address. */
++ spi_ptr->np_spistatus=0;
++
++ /* empty the np_spirxdata register */
++ SPI_Recv_Byte(&temp);
++
++ for ( i = sizeof(u16); i<count; i++ )
++ {
++ /* send the address */
++ timeout=SPI_BUSYPOLL_TIMEOUT;
++ while (SPI_Send_Byte(addr, 0)==-1)
++ {
++ if (--timeout==0)
++ {
++ printk("spi_read write address time out\n");
++ return i;
++ }
++ }
++
++ /* read the data */
++ timeout=SPI_BUSYPOLL_TIMEOUT;
++ while (SPI_Recv_Byte(&buf[i])==-1)
++ {
++ if (--timeout==0)
++ {
++ printk("spi_read read data time out\n");
++ return i;
++ }
++ }
++#if 0
++ printk("spi_read time left %d\n", timeout);
++#endif
++ }
++ return i;
++}
++
++loff_t spi_lseek(struct file *filp, loff_t offset, int origin)
++{
++#if 0
++ int bit_count, i;
++#endif
++
++ if ( origin != SEEK_SET || offset != (offset & 0xFFFF) )
++ {
++ errno = -EINVAL;
++ return -1;
++ }
++
++#if 0
++ /****************************************/
++ /* Nios SPI implementation safeguard: */
++ /* It is possible to have more than */
++ /* one CS active at a time. Check that */
++ /* the given address is a power of two. */
++ /****************************************/
++ bit_count = 0;
++ for ( i = 0; i < sizeof(u16); i++ )
++ {
++ if ( (1 << i) & offset )
++ {
++ if ( ++bit_count > 1 )
++ {
++ errno = -EINVAL;
++ return -1;
++ }
++ }
++ }
++#endif
++ spi_ptr->np_spislaveselect = offset;
++ return 0;
++}
++
++int spi_open(struct inode *inode, struct file *filp)
++{
++ preempt_disable();
++ if (openflag) {
++ preempt_enable();
++ return -EBUSY;
++ }
++
++ MOD_INC_USE_COUNT;
++ openflag = 1;
++ preempt_enable();
++
++ return 0;
++}
++
++int spi_release(struct inode *inode, struct file *filp)
++{
++ openflag = 0;
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++
++/* static struct file_operations spi_fops */
++
++static struct file_operations spi_fops = {
++ llseek: spi_lseek, /* Set chip-select line. The offset is used as an address. */
++ read: spi_read,
++ write: spi_write,
++ open: spi_open,
++ release: spi_release,
++};
++
++
++int register_NIOS_SPI( void )
++{
++ int result = register_chrdev( spi_major, "spi", &spi_fops );
++ if ( result < 0 )
++ {
++ printk( "SPI: unable to get major %d for SPI bus \n", spi_major );
++ return result;
++ }/*end-if*/
++
++ if ( spi_major == 0 )
++ spi_major = result; /* here we got our major dynamically */
++
++ /* reserve our port, but check first if free */
++ if ( check_region( (unsigned int)na_spi, sizeof(np_spi) ) )
++ {
++ printk( "SPI: port at adr 0x%08x already occupied\n", (unsigned int)na_spi );
++ unregister_chrdev( spi_major, "spi" );
++
++ return result;
++ }/*end-if*/
++
++ return 0;
++}
++
++void unregister_NIOS_SPI( void )
++{
++ if ( spi_major > 0 )
++ unregister_chrdev( spi_major, "spi" );
++
++ release_region( (unsigned int)na_spi, sizeof(np_spi) );
++}
++
++
++#ifdef MODULE
++void cleanup_module( void )
++{
++ unregister_NIOS_SPI();
++}
++
++
++
++int init_module( void )
++{
++ return register_NIOS_SPI();
++}
++#endif
++
++
++static int __init nios_spi_init(void)
++{
++ printk("SPI: Nios SPI bus device version 0.1\n");
++ return register_NIOS_SPI();
++// if ( register_NIOS_SPI() )
++// printk("*** Cannot initialize SPI device.\n");
++}
++
++__initcall(nios_spi_init);
+diff --git a/arch/nios2nommu/kernel/ChangeLog b/arch/nios2nommu/kernel/ChangeLog
+new file mode 100644
+index 0000000..7f1449d
+--- /dev/null
++++ b/arch/nios2nommu/kernel/ChangeLog
+@@ -0,0 +1,27 @@
++2004-06-17 Ken Hill <khill@microtronix.com>
++
++ * process.c (machine_restart): Add code to disable interrups and
++ jump to the cpu reset address.
++ (machine_halt): Add code to disable interrupts and spinlock.
++ (machine_power_off): Add code to disable interrupts and spinlock.
++
++2004-06-16 Ken Hill <khill@microtronix.com>
++
++ * nios2_ksyms.c: Remove hard_reset_now.
++
++2004-06-10 Ken Hill <khill@microtronix.com>
++
++ * nios2_ksyms.c: Add EXPORT_SYMBOL_NOVERS(__down) to solve insmod for
++ some modules.
++
++2004-06-02 Ken Hill <khill@microtronix.com>
++
++ * entry.S (software_exception): Add a safety catch for old applications that may
++ have been linked against an older library. This does not add any overhead to
++ system call processing.
++
++2004-04-15 Ken Hill <khill@microtronix.com>
++
++ * setup.c (setup_arch): Remove ROMFS message from debug printk kernel message.
++ Add copyright and GNU license notice.
++
+diff --git a/arch/nios2nommu/kernel/Makefile b/arch/nios2nommu/kernel/Makefile
+new file mode 100644
+index 0000000..a056ff1
+--- /dev/null
++++ b/arch/nios2nommu/kernel/Makefile
+@@ -0,0 +1,22 @@
++#
++# Makefile for the linux kernel.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definitions are now in the main makefile...
++
++extra-y := head.o init_task.o vmlinux.lds
++
++obj-y := entry.o traps.o irq.o syscalltable.o \
++ process.o signal.o setup.o sys_nios2.o \
++ semaphore.o io.o usb.o\
++ time.o ptrace.o start.o nios2_ksyms.o
++
++obj-$(CONFIG_MODULES) += module.o
++obj-$(CONFIG_CONSOLE) += console.o
++obj-$(CONFIG_PIO_DEVICES) += pio.o
++obj-$(CONFIG_AVALON_DMA) += dma.o
++
++
+diff --git a/arch/nios2nommu/kernel/asm-offsets.c b/arch/nios2nommu/kernel/asm-offsets.c
+new file mode 100644
+index 0000000..4877eba
+--- /dev/null
++++ b/arch/nios2nommu/kernel/asm-offsets.c
+@@ -0,0 +1,201 @@
++/*
++ * This program is used to generate definitions needed by
++ * assembly language modules.
++ *
++ * We use the technique used in the OSF Mach kernel code:
++ * generate asm statements containing #defines,
++ * compile this file to assembler, and then extract the
++ * #defines from the assembly-language output.
++ */
++
++#include <linux/stddef.h>
++#include <linux/sched.h>
++#include <linux/kernel_stat.h>
++#include <linux/ptrace.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/hardirq.h>
++#include <asm/nios.h>
++
++#define DEFINE(sym, val) \
++ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++
++#define BLANK() asm volatile("\n->" : : )
++
++int main(void)
++{
++
++ /* offsets into the task struct */
++ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
++ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
++ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
++ DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
++ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
++ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
++ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
++ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
++
++ /* offsets into the kernel_stat struct */
++ DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
++
++ /* offsets into the irq_cpustat_t struct */
++ DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
++
++ /* offsets into the irq_node struct */
++ DEFINE(IRQ_HANDLER, offsetof(struct irq_hand, handler));
++ DEFINE(IRQ_FLAGS, offsetof(struct irq_hand, flags));
++ DEFINE(IRQ_DEV_ID, offsetof(struct irq_hand, dev_id));
++ DEFINE(IRQ_DEVNAME, offsetof(struct irq_hand, devname));
++
++ /* offsets into the thread struct */
++ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
++ DEFINE(THREAD_KPSR, offsetof(struct thread_struct, kpsr));
++ DEFINE(THREAD_KESR, offsetof(struct thread_struct, kesr));
++ DEFINE(THREAD_FLAGS, offsetof(struct thread_struct, flags));
++
++ /* offsets into the pt_regs */
++ DEFINE(PT_ORIG_R2, offsetof(struct pt_regs, orig_r2));
++ DEFINE(PT_R1, offsetof(struct pt_regs, r1));
++ DEFINE(PT_R2, offsetof(struct pt_regs, r2));
++ DEFINE(PT_R3, offsetof(struct pt_regs, r3));
++ DEFINE(PT_R4, offsetof(struct pt_regs, r4));
++ DEFINE(PT_R5, offsetof(struct pt_regs, r5));
++ DEFINE(PT_R6, offsetof(struct pt_regs, r6));
++ DEFINE(PT_R7, offsetof(struct pt_regs, r7));
++ DEFINE(PT_R8, offsetof(struct pt_regs, r8));
++ DEFINE(PT_R9, offsetof(struct pt_regs, r9));
++ DEFINE(PT_R10, offsetof(struct pt_regs, r10));
++ DEFINE(PT_R11, offsetof(struct pt_regs, r11));
++ DEFINE(PT_R12, offsetof(struct pt_regs, r12));
++ DEFINE(PT_R13, offsetof(struct pt_regs, r13));
++ DEFINE(PT_R14, offsetof(struct pt_regs, r14));
++ DEFINE(PT_R15, offsetof(struct pt_regs, r15));
++ DEFINE(PT_EA, offsetof(struct pt_regs, ea));
++ DEFINE(PT_RA, offsetof(struct pt_regs, ra));
++ DEFINE(PT_FP, offsetof(struct pt_regs, fp));
++ DEFINE(PT_SP, offsetof(struct pt_regs, sp));
++ DEFINE(PT_GP, offsetof(struct pt_regs, gp));
++ DEFINE(PT_ESTATUS, offsetof(struct pt_regs, estatus));
++ DEFINE(PT_STATUS_EXTENSION, offsetof(struct pt_regs, status_extension));
++ DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
++
++ /* offsets into the switch_stack */
++ DEFINE(SW_R16, offsetof(struct switch_stack, r16));
++ DEFINE(SW_R17, offsetof(struct switch_stack, r17));
++ DEFINE(SW_R18, offsetof(struct switch_stack, r18));
++ DEFINE(SW_R19, offsetof(struct switch_stack, r19));
++ DEFINE(SW_R20, offsetof(struct switch_stack, r20));
++ DEFINE(SW_R21, offsetof(struct switch_stack, r21));
++ DEFINE(SW_R22, offsetof(struct switch_stack, r22));
++ DEFINE(SW_R23, offsetof(struct switch_stack, r23));
++ DEFINE(SW_FP, offsetof(struct switch_stack, fp));
++ DEFINE(SW_GP, offsetof(struct switch_stack, gp));
++ DEFINE(SW_RA, offsetof(struct switch_stack, ra));
++ DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack));
++
++ DEFINE(PS_S_ASM, PS_S);
++
++ DEFINE(NIOS2_STATUS_PIE_MSK_ASM, NIOS2_STATUS_PIE_MSK);
++ DEFINE(NIOS2_STATUS_PIE_OFST_ASM, NIOS2_STATUS_PIE_OFST);
++ DEFINE(NIOS2_STATUS_U_MSK_ASM, NIOS2_STATUS_U_MSK);
++ DEFINE(NIOS2_STATUS_U_OFST_ASM, NIOS2_STATUS_U_OFST);
++
++ /* offsets into the kernel_stat struct */
++ DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
++
++ /* Offsets in thread_info structure, used in assembly code */
++ DEFINE(TI_TASK, offsetof(struct thread_info, task));
++ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
++ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
++ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
++ DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count));
++
++ DEFINE(PREEMPT_ACTIVE_ASM, PREEMPT_ACTIVE);
++
++ DEFINE(THREAD_SIZE_ASM, THREAD_SIZE);
++
++ DEFINE(TIF_SYSCALL_TRACE_ASM, TIF_SYSCALL_TRACE);
++ DEFINE(TIF_NOTIFY_RESUME_ASM, TIF_NOTIFY_RESUME);
++ DEFINE(TIF_SIGPENDING_ASM, TIF_SIGPENDING);
++ DEFINE(TIF_NEED_RESCHED_ASM, TIF_NEED_RESCHED);
++ DEFINE(TIF_POLLING_NRFLAG_ASM, TIF_POLLING_NRFLAG);
++
++ DEFINE(_TIF_SYSCALL_TRACE_ASM, _TIF_SYSCALL_TRACE);
++ DEFINE(_TIF_NOTIFY_RESUME_ASM, _TIF_NOTIFY_RESUME);
++ DEFINE(_TIF_SIGPENDING_ASM, _TIF_SIGPENDING);
++ DEFINE(_TIF_NEED_RESCHED_ASM, _TIF_NEED_RESCHED);
++ DEFINE(_TIF_POLLING_NRFLAG_ASM, _TIF_POLLING_NRFLAG);
++
++ DEFINE(_TIF_WORK_MASK_ASM, _TIF_WORK_MASK);
++
++#if defined(na_flash_kernel) && defined(na_flash_kernel_end)
++ /* the flash chip */
++ DEFINE(NIOS_FLASH_START, na_flash_kernel);
++ DEFINE(NIOS_FLASH_END, na_flash_kernel_end);
++
++ /* the kernel placement in the flash*/
++ DEFINE(KERNEL_FLASH_START, na_flash_kernel);
++ DEFINE(KERNEL_FLASH_LEN, 0x200000);
++
++ /* the romdisk placement in the flash */
++ DEFINE(LINUX_ROMFS_START, na_flash_kernel+0x200000);
++ DEFINE(LINUX_ROMFS_END, na_flash_kernel_end);
++#else
++#error Sorry,you dont have na_flash_kernel or na_flash_kernel_end defined in the core.
++#endif
++
++#if defined(nasys_program_mem) && defined(nasys_program_mem_end)
++ /* the sdram */
++ DEFINE(LINUX_SDRAM_START, nasys_program_mem);
++ DEFINE(LINUX_SDRAM_END, nasys_program_mem_end);
++#else
++#error Sorry,you dont have nasys_program_mem or nasys_program_mem_end defined in the core.
++#endif
++
++ DEFINE(NIOS2_ICACHE_SIZE, nasys_icache_size);
++ DEFINE(NIOS2_ICACHE_LINE_SIZE, nasys_icache_line_size);
++ DEFINE(NIOS2_DCACHE_SIZE, nasys_dcache_size);
++ DEFINE(NIOS2_DCACHE_LINE_SIZE, nasys_dcache_line_size);
++
++#if defined(na_enet)
++ DEFINE(NA_ENET_ASM, na_enet);
++#endif
++
++#if defined(na_enet_reset)
++ DEFINE(NA_ENET_RESET_ASM, na_enet_reset);
++#endif
++
++#if defined(na_enet_reset_n)
++ DEFINE(NA_ENET_RESET_N_ASM, na_enet_reset_n);
++#endif
++
++#if defined(na_ide_interface)
++ DEFINE(NA_IDE_INTERFACE_ASM, na_ide_interface);
++#endif
++
++#if defined(na_timer0)
++ DEFINE(NA_TIMER0_ASM, na_timer0);
++ DEFINE(NP_TIMERCONTROL_ASM, offsetof(np_timer, np_timercontrol));
++ DEFINE(NP_TIMERSTATUS_ASM, offsetof(np_timer, np_timerstatus));
++#endif
++
++#if defined(na_uart0)
++ DEFINE(NA_UART0_ASM, na_uart0);
++ DEFINE(NP_UARTCONTROL_ASM, offsetof(np_uart, np_uartcontrol));
++ DEFINE(NP_UARTSTATUS_ASM, offsetof(np_uart, np_uartstatus));
++#endif
++
++#if defined(na_uart1)
++ DEFINE(NA_UART1_ASM, na_uart1);
++#endif
++
++#if defined(na_uart2)
++ DEFINE(NA_UART2_ASM, na_uart2);
++#endif
++
++#if defined(na_uart3)
++ DEFINE(NA_UART3_ASM, na_uart3);
++#endif
++
++ return 0;
++}
+diff --git a/arch/nios2nommu/kernel/dma.c b/arch/nios2nommu/kernel/dma.c
+new file mode 100644
+index 0000000..f23323b
+--- /dev/null
++++ b/arch/nios2nommu/kernel/dma.c
+@@ -0,0 +1,342 @@
++/*
++ * arch/nios2nommu/kernel/dma.c
++ *
++ * Copyright (C) 2005 Microtronix Datacom Ltd
++ *
++ * PC like DMA API for Nios's DMAC.
++ *
++ * 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.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/seq_file.h>
++#include <linux/proc_fs.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++/* nios2 dma controller register map */
++#define REG_DMA_STATUS 0
++#define REG_DMA_READADDR 4
++#define REG_DMA_WRITEADDR 8
++#define REG_DMA_LENGTH 12
++#define REG_DMA_CONTROL 24
++
++/* status register bits definition */
++#define ST_DONE 0x01
++#define ST_BUSY 0x02
++#define ST_REOP 0x04
++#define ST_WROP 0x08
++#define ST_LEN 0x10
++
++/* control register bits definition */
++#define CT_BYTE 0x01
++#define CT_HW 0x02
++#define CT_WORD 0x04
++#define CT_GO 0x08
++#define CT_IEEN 0x10
++#define CT_REEN 0x20
++#define CT_WEEN 0x40
++#define CT_LEEN 0x80
++#define CT_RCON 0x100
++#define CT_WCON 0x200
++#define CT_DOUBLE 0x400
++#define CT_QUAD 0x800
++
++struct dma_channel {
++ unsigned int addr; /* control address */
++ unsigned int irq; /* interrupt number */
++ atomic_t idle;
++ unsigned int mode; /* dma mode: width, stream etc */
++ int (*handler)(void*, int );
++ void* user;
++
++ char id[16];
++ char dev_id[16];
++};
++static struct dma_channel dma_channels[]={
++#ifdef na_dma_0
++ {
++ .addr = na_dma_0,
++ .irq = na_dma_0_irq,
++ .idle = ATOMIC_INIT(1),
++ },
++#endif
++#ifdef na_dma_1
++ {
++ .addr = na_dma_1,
++ .irq = na_dma_1_irq,
++ .idle = ATOMIC_INIT(1),
++ },
++#endif
++};
++#define MAX_DMA_CHANNELS sizeof(dma_channels)/sizeof(struct dma_channel)
++
++void enable_dma(unsigned int dmanr)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ unsigned int ctl = dma_channels[dmanr].mode;
++ ctl |= CT_GO | CT_IEEN;
++ outl(ctl, dma_channels[dmanr].addr+REG_DMA_CONTROL);
++ }
++}
++
++void disable_dma(unsigned int dmanr)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ unsigned int ctl = dma_channels[dmanr].mode;
++ ctl &= ~(CT_GO | CT_IEEN);
++ outl(ctl, dma_channels[dmanr].addr+REG_DMA_CONTROL);
++ }
++}
++
++void set_dma_count(unsigned int dmanr, unsigned int count)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ dma_channels[dmanr].mode |= CT_LEEN;
++ outl(count, dma_channels[dmanr].addr+REG_DMA_LENGTH);
++ }
++}
++
++int get_dma_residue(unsigned int dmanr)
++{
++ int result =-1;
++ if (dmanr < MAX_DMA_CHANNELS) {
++ result = inl(dma_channels[dmanr].addr+REG_DMA_LENGTH);
++ }
++ return result;
++}
++
++int request_dma(unsigned int chan, const char *dev_id)
++{
++ struct dma_channel *channel;
++
++ if ( chan >= MAX_DMA_CHANNELS) {
++ return -EINVAL;
++ }
++
++ channel = &dma_channels[chan];
++
++ if (!atomic_dec_and_test(&channel->idle)) {
++ return -EBUSY;
++ }
++
++ strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
++ channel->handler=NULL;
++ channel->user=NULL;
++ channel->mode =0;
++
++ return 0;
++}
++
++void free_dma(unsigned int chan)
++{
++ if ( chan < MAX_DMA_CHANNELS) {
++ dma_channels[chan].handler=NULL;
++ dma_channels[chan].user=NULL;
++ atomic_set(&dma_channels[chan].idle, 1);
++ }
++}
++
++int nios2_request_dma(const char *dev_id)
++{
++ int chann;
++
++ for ( chann=0; chann < MAX_DMA_CHANNELS; chann++) {
++ if (request_dma(chann, dev_id)==0)
++ return chann;
++ }
++
++ return -EINVAL;
++}
++void nios2_set_dma_handler(unsigned int dmanr, int (*handler)(void*, int), void* user)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ dma_channels[dmanr].handler=handler;
++ dma_channels[dmanr].user=user;
++ }
++}
++#define NIOS2_DMA_WIDTH_MASK (CT_BYTE | CT_HW | CT_WORD | CT_DOUBLE | CT_QUAD)
++#define NIOS2_MODE_MASK (NIOS2_DMA_WIDTH_MASK | CT_REEN | CT_WEEN | CT_LEEN | CT_RCON | CT_WCON)
++void nios2_set_dma_data_width(unsigned int dmanr, unsigned int width)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ dma_channels[dmanr].mode &= ~NIOS2_DMA_WIDTH_MASK;
++ switch (width) {
++ case 1:
++ dma_channels[dmanr].mode |= CT_BYTE;
++ break;
++ case 2:
++ dma_channels[dmanr].mode |= CT_HW;
++ break;
++ case 8:
++ dma_channels[dmanr].mode |= CT_DOUBLE;
++ break;
++ case 16:
++ dma_channels[dmanr].mode |= CT_QUAD;
++ break;
++ case 4:
++ default:
++ dma_channels[dmanr].mode |= CT_WORD;
++ break;
++ }
++ }
++}
++
++void nios2_set_dma_rcon(unsigned int dmanr,unsigned int set)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ dma_channels[dmanr].mode &= ~(CT_REEN | CT_RCON);
++ if (set)
++ dma_channels[dmanr].mode |= (CT_REEN | CT_RCON);
++ }
++}
++void nios2_set_dma_wcon(unsigned int dmanr,unsigned int set)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ dma_channels[dmanr].mode &= ~(CT_WEEN | CT_WCON);
++ if (set)
++ dma_channels[dmanr].mode |= (CT_WEEN | CT_WCON);
++ }
++}
++void nios2_set_dma_mode(unsigned int dmanr, unsigned int mode)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ /* set_dma_mode is only allowed to change the bus width,
++ stream setting, etc.
++ */
++ mode &= NIOS2_MODE_MASK;
++ dma_channels[dmanr].mode &= ~NIOS2_MODE_MASK;
++ dma_channels[dmanr].mode |= mode;
++ }
++}
++
++void nios2_set_dma_raddr(unsigned int dmanr, unsigned int a)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ outl(a, dma_channels[dmanr].addr+REG_DMA_READADDR);
++ }
++}
++void nios2_set_dma_waddr(unsigned int dmanr, unsigned int a)
++{
++ if (dmanr < MAX_DMA_CHANNELS) {
++ outl(a, dma_channels[dmanr].addr+REG_DMA_WRITEADDR);
++ }
++}
++
++
++static irqreturn_t dma_isr(int irq, void *dev_id)
++{
++ struct dma_channel *chann=(struct dma_channel*)dev_id;
++
++ if (chann) {
++ int status = inl(chann->addr+REG_DMA_STATUS);
++ /* ack the interrupt, and clear the DONE bit */
++ outl(0, chann->addr+REG_DMA_STATUS);
++ /* call the peripheral callback */
++ if (chann->handler)
++ chann->handler(chann->user, status);
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++
++#ifdef CONFIG_PROC_FS
++static int proc_dma_show(struct seq_file *m, void *v)
++{
++ int i;
++
++ for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
++ if (!atomic_read(&dma_channels[i].idle)) {
++ seq_printf(m, "%2d: %s\n", i,
++ dma_channels[i].dev_id);
++ }
++ }
++ return 0;
++}
++
++static int proc_dma_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, proc_dma_show, NULL);
++}
++static struct file_operations proc_dma_operations = {
++ .open = proc_dma_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init proc_dma_init(void)
++{
++ struct proc_dir_entry *e;
++
++ e = create_proc_entry("dma", 0, NULL);
++ if (e)
++ e->proc_fops = &proc_dma_operations;
++
++ return 0;
++}
++
++__initcall(proc_dma_init);
++
++#endif /* CONFIG_PROC_FS */
++
++int __init init_dma(void)
++{
++ int i;
++
++ for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
++ sprintf(dma_channels[i].id, "dmac-%d", i);
++ /* disable the dmac channel */
++ disable_dma(i);
++ /* request irq*/
++ if (request_irq(dma_channels[i].irq, dma_isr, 0, dma_channels[i].id, (void*)&dma_channels[i])){
++ printk("DMA controller %d failed to get irq %d\n", i, dma_channels[i].irq);
++ atomic_set(&dma_channels[i].idle, 0);
++ }
++ }
++ return 0;
++}
++
++static void __exit exit_dma(void)
++{
++ int i;
++
++ for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
++ /* disable the dmac channel */
++ disable_dma(i);
++ free_irq(dma_channels[i].irq, dma_channels[i].id);
++ }
++}
++
++module_init(init_dma);
++module_exit(exit_dma);
++
++MODULE_LICENSE("GPL");
++
++//EXPORT_SYMBOL(claim_dma_lock);
++//EXPORT_SYMBOL(release_dma_lock);
++EXPORT_SYMBOL(enable_dma);
++EXPORT_SYMBOL(disable_dma);
++EXPORT_SYMBOL(set_dma_count);
++EXPORT_SYMBOL(get_dma_residue);
++EXPORT_SYMBOL(request_dma);
++EXPORT_SYMBOL(free_dma);
++EXPORT_SYMBOL(nios2_request_dma);
++EXPORT_SYMBOL(nios2_set_dma_handler);
++EXPORT_SYMBOL(nios2_set_dma_data_width);
++EXPORT_SYMBOL(nios2_set_dma_rcon);
++EXPORT_SYMBOL(nios2_set_dma_wcon);
++EXPORT_SYMBOL(nios2_set_dma_mode);
++EXPORT_SYMBOL(nios2_set_dma_raddr);
++EXPORT_SYMBOL(nios2_set_dma_waddr);
++
+diff --git a/arch/nios2nommu/kernel/entry.S b/arch/nios2nommu/kernel/entry.S
+new file mode 100644
+index 0000000..7f71a01
+--- /dev/null
++++ b/arch/nios2nommu/kernel/entry.S
+@@ -0,0 +1,898 @@
++/*
++ * linux/arch/nios2nommu/kernel/entry.S
++ *
++ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
++ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
++ * Kenneth Albanowski <kjahds@kjahds.com>,
++ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * Based on:
++ *
++ * linux/arch/m68knommu/kernel/entry.S
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file README.legal in the main directory of this archive
++ * for more details.
++ *
++ * Linux/m68k support by Hamish Macdonald
++ *
++ * 68060 fixes by Jesper Skov
++ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
++ * 5307 fixes by David W. Miller
++ * linux 2.4 support David McCullough <davidm@snapgear.com>
++ */
++
++#include <linux/sys.h>
++#include <linux/linkage.h>
++#include <asm/asm-offsets.h>
++#include <asm/asm-macros.h>
++#include <asm/thread_info.h>
++#include <asm/errno.h>
++#include <asm/setup.h>
++#include <asm/segment.h>
++#include <asm/entry.h>
++#include <asm/unistd.h>
++#include <asm/traps.h>
++#include <asm/processor.h>
++
++.text
++.set noat
++.set nobreak
++
++ENTRY(system_call)
++/* SAVE_ALL */
++ rdctl r10,status /* enable intrs again */
++ ori r10,r10,0x0001
++ wrctl status,r10
++
++ movi r2,-LENOSYS
++ stw r2,PT_R2(sp) /* default return value in r2 */
++ /* original r2 is in orig_r2 */
++
++ movui r1,NR_syscalls
++ bgtu r3,r1,ret_from_exception
++ slli r1,r3,2
++ movhi r11,%hiadj(sys_call_table)
++ add r1,r1,r11
++ ldw r1,%lo(sys_call_table)(r1)
++ beq r1,r0,ret_from_exception
++
++ movi r11,%lo(0xffffe000) /* Get thread info pointer */
++ and r11,sp,r11
++ ldw r11,TI_FLAGS(r11)
++ BTBNZ r11,r11,TIF_SYSCALL_TRACE_ASM,1f
++
++ callr r1
++ stw r2,PT_R2(sp) /* save the return value */
++ br ret_from_exception
++1:
++ SAVE_SWITCH_STACK
++ call syscall_trace
++ RESTORE_SWITCH_STACK
++ /* wentao: restore r4-9, since they are trashed by syscall_trace */
++ ldw r4,PT_R4(sp)
++ ldw r5,PT_R5(sp)
++ ldw r6,PT_R6(sp)
++ ldw r7,PT_R7(sp)
++ ldw r8,PT_R8(sp)
++ ldw r9,PT_R9(sp)
++ callr r1
++ stw r2,PT_R2(sp) /* save the return value */
++ SAVE_SWITCH_STACK
++ call syscall_trace
++ RESTORE_SWITCH_STACK
++
++ret_from_exception:
++ ldw r1,PT_STATUS_EXTENSION(sp) /* check if returning to kernel */
++ TSTBZ r1,r1,PS_S_ASM,Luser_return /* if so, skip resched, signals */
++
++restore_all:
++ rdctl r10,status /* disable intrs */
++ andi r10,r10,0xfffe
++ wrctl status, r10
++ RESTORE_ALL
++ eret
++
++Luser_return:
++ GET_THREAD_INFO r24 /* get thread_info pointer */
++ ldw r10,TI_FLAGS(r24) /* get thread_info->flags */
++ ANDI32 r11,r10,_TIF_WORK_MASK_ASM
++ beq r11,r0,restore_all /* Nothing to do */
++ BTBZ r1,r10,TIF_NEED_RESCHED_ASM,Lsignal_return
++
++Lwork_resched:
++ call schedule
++ br ret_from_exception
++
++Lsignal_return:
++ BTBZ r1,r10,TIF_SIGPENDING_ASM,restore_all
++ mov r5,sp /* pt_regs */
++ SAVE_SWITCH_STACK
++ CLR r4 /* oldset = 0 */
++ call do_signal
++ RESTORE_SWITCH_STACK
++ br restore_all
++
++/*
++ * Handle software exceptions. Put here so external interrupts
++ * can fall throught to ret_from_interrupt.
++ */
++
++software_exception:
++ ldw r24,-4(ea) // instruction that caused the exception
++ xorhi r24,r24,0x003b // upper half of trap opcode
++ xori r24,r24,0x683a // lower half of trap opcode
++ bne r24,r0,instruction_trap /* N - check for instruction trap */
++ cmpeqi r11,r2,TRAP_ID_SYSCALL /* ? Is this a syscall */
++ bne r11,r0,system_call /* Y - handle syscall */
++ cmpeqi r11,r2,TRAP_ID_APPDEBUG /* ? Is this an application debug */
++ bne r11,r0,app_debug /* Y - handle app_debug */
++ cmpeqi r11,r2,63 /* ? Is this the old syscall number */
++ bne r11,r0,system_call /* Y - handle syscall to catch older apps*/
++ br restore_all /* N - everything else is ignored for now */
++
++app_debug:
++ GET_THREAD_INFO r24 /* get thread_info */
++ ldw r1,TI_TASK(r24) /* get thread_info->task */
++ ldw r24,(TASK_THREAD + THREAD_FLAGS)(r1) /* get thread_info->task->thread.flags */
++ ORI32 r24, r24, NIOS2_FLAG_DEBUG /* set the debug flag */
++ stw r24,(TASK_THREAD + THREAD_FLAGS)(r1) /* save thread_info->task->thread.flags */
++ br restore_all
++
++/*
++ * This is the generic interrupt handler (for all hardware interrupt
++ * sources). It figures out the vector number and calls the appropriate
++ * interrupt service routine directly.
++ */
++ENTRY(inthandler)
++ SAVE_ALL
++ /*
++ * Test to see if the exception was a software exception or caused by an
++ * external interrupt, and vector accordingly.
++ */
++
++ rdctl r24,estatus
++ andi r24,r24,1
++ beq r24,r0,software_exception
++ rdctl r12,ipending
++ beq r12,r0,software_exception
++
++ movi r24,-1
++ stw r24,PT_ORIG_R2(sp)
++
++ /*
++ * Process an external hardware interrupt.
++ */
++
++ addi ea,ea,-4 /* re-issue the interrupted instruction */
++ stw ea,PT_EA(sp)
++ rdctl r9,ienable /* Isolate possible interrupts */
++ and r12,r12,r9
++ beq r12,r0,ret_from_interrupt /* No one to service done */
++ movi r4,%lo(-1) /* Start from bit position 0, highest priority */
++ /* This is the IRQ # for handler call */
++1: addi r4,r4,1
++ srl r10,r12,r4
++ andi r10,r10,1 /* Isolate bit we are interested in */
++ cmpeqi r11,r4,32 /* ? End of the register */
++ bne r11,r0,ret_from_interrupt /* Y - out of here */
++ beq r10,r0,1b
++ mov r5,sp /* Setup pt_regs pointer for handler call */
++ PUSH r4 /* Save state for return */
++ PUSH r12
++ call process_int
++ POP r12
++ POP r4
++ br 1b /* Check for other interrupts while here */
++
++ENTRY(ret_from_interrupt)
++ ldw r4,PT_STATUS_EXTENSION(sp)
++ TSTBZ r4,r4,PS_S_ASM,Luser_return // Returning to user
++
++#ifdef CONFIG_PREEMPT
++ GET_THREAD_INFO r1
++ ldw r4,TI_PREEMPT_COUNT(r1)
++ bne r4,r0,restore_all
++
++need_resched:
++ ldw r4,TI_FLAGS(r1) // ? Need resched set
++ BTBZ r10,r4,TIF_NEED_RESCHED_ASM,restore_all
++ ldw r4,PT_ESTATUS(sp) // ? Interrupts off
++ BTBZ r10,r4,NIOS2_STATUS_PIE_OFST_ASM,restore_all
++ movia r4,PREEMPT_ACTIVE_ASM
++ stw r4,TI_PREEMPT_COUNT(r1)
++ rdctl r10,status /* enable intrs again */
++ ori r10,r10,0x0001
++ wrctl status,r10
++ PUSH r1
++ call schedule
++ POP r1
++ mov r4,r0
++ stw r4,TI_PREEMPT_COUNT(r1)
++ rdctl r10,status /* disable intrs */
++ andi r10,r10,0xfffe
++ wrctl status, r10
++ br need_resched
++#else
++ br restore_all
++#endif
++
++
++/*
++ * Beware - when entering resume, prev (the current task) is
++ * in r4, next (the new task) is in r5, don't change these
++ * registers.
++ */
++ENTRY(resume)
++
++ rdctl r7,status /* save thread status reg */
++ stw r7,TASK_THREAD+THREAD_KPSR(r4)
++
++ andi r7,r7,0x0fffe /* disable interrupts */
++ wrctl status,r7
++
++ movia r8,status_extension /* save status extension */
++ ldw r7,0(r8)
++ stw r7,TASK_THREAD+THREAD_KESR(r4)
++
++ SAVE_SWITCH_STACK
++ stw sp,TASK_THREAD+THREAD_KSP(r4) /* save kernel stack pointer */
++ ldw sp,TASK_THREAD+THREAD_KSP(r5) /* restore new thread stack */
++ movia r24,_current_thread /* save thread */
++ GET_THREAD_INFO r1
++ stw r1,0(r24)
++ RESTORE_SWITCH_STACK
++
++ ldw r7,TASK_THREAD+THREAD_KESR(r5) /* restore extended status reg */
++ stw r7,0(r8)
++
++ ldw r7,TASK_THREAD+THREAD_KPSR(r5) /* restore thread status reg */
++ wrctl status,r7
++ ret
++
++ENTRY(ret_from_fork)
++ call schedule_tail
++ br ret_from_exception
++
++ENTRY(sys_fork)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call nios2_vfork
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_vfork)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call nios2_vfork
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_execve)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call nios2_execve
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_clone)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call nios2_clone
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_sigsuspend)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call do_sigsuspend
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_rt_sigsuspend)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call do_rt_sigsuspend
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_sigreturn)
++ mov r4,sp
++ SAVE_SWITCH_STACK
++ call do_sigreturn
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_sigaltstack)
++ ldw r4,PT_R4(sp)
++ ldw r5,PT_R5(sp)
++ ldw r6,PT_SP(sp)
++ SAVE_SWITCH_STACK
++ call do_sigaltstack
++ RESTORE_SWITCH_STACK
++ ret
++
++ENTRY(sys_rt_sigreturn)
++ SAVE_SWITCH_STACK
++ call do_rt_sigreturn
++ RESTORE_SWITCH_STACK
++ ret
++
++/******************************************************************************
++* *
++* License Agreement *
++* *
++* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. *
++* All rights reserved. *
++* *
++* Permission is hereby granted, free of charge, to any person obtaining a *
++* copy of this software and associated documentation files (the "Software"), *
++* to deal in the Software without restriction, including without limitation *
++* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
++* and/or sell copies of the Software, and to permit persons to whom the *
++* Software is furnished to do so, subject to the following conditions: *
++* *
++* The above copyright notice and this permission notice shall be included in *
++* all copies or substantial portions of the Software. *
++* *
++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
++* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
++* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
++* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
++* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
++* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
++* DEALINGS IN THE SOFTWARE. *
++* *
++* This agreement shall be governed in all respects by the laws of the State *
++* of California and by the laws of the United States of America. *
++* *
++******************************************************************************/
++
++ /*
++ * This is the software exception handler for Nios2.
++ */
++
++ /*
++ * Explicitly allow the use of r1 (the assembler temporary register)
++ * within this code. This register is normally reserved for the use of
++ * the compiler.
++ */
++
++ENTRY(instruction_trap)
++ RESTORE_ALL // Clean off our save & setup for emulation
++
++ /* INSTRUCTION EMULATION
++ * ---------------------
++ *
++ * Nios II processors generate exceptions for unimplemented instructions.
++ * The routines below emulate these instructions. Depending on the
++ * processor core, the only instructions that might need to be emulated
++ * are div, divu, mul, muli, mulxss, mulxsu, and mulxuu.
++ *
++ * The emulations match the instructions, except for the following
++ * limitations:
++ *
++ * 1) The emulation routines do not emulate the use of the exception
++ * temporary register (et) as a source operand because the exception
++ * handler already has modified it.
++ *
++ * 2) The routines do not emulate the use of the stack pointer (sp) or the
++ * exception return address register (ea) as a destination because
++ * modifying these registers crashes the exception handler or the
++ * interrupted routine.
++ *
++ * Detailed Design
++ * ---------------
++ *
++ * The emulation routines expect the contents of integer registers r0-r31
++ * to be on the stack at addresses sp, 4(sp), 8(sp), ... 124(sp). The
++ * routines retrieve source operands from the stack and modify the
++ * destination register's value on the stack prior to the end of the
++ * exception handler. Then all registers except the destination register
++ * are restored to their previous values.
++ *
++ * The instruction that causes the exception is found at address -4(ea).
++ * The instruction's OP and OPX fields identify the operation to be
++ * performed.
++ *
++ * One instruction, muli, is an I-type instruction that is identified by
++ * an OP field of 0x24.
++ *
++ * muli AAAAA,BBBBB,IIIIIIIIIIIIIIII,-0x24-
++ * 27 22 6 0 <-- LSB of field
++ *
++ * The remaining emulated instructions are R-type and have an OP field
++ * of 0x3a. Their OPX fields identify them.
++ *
++ * R-type AAAAA,BBBBB,CCCCC,XXXXXX,NNNNN,-0x3a-
++ * 27 22 17 11 6 0 <-- LSB of field
++ *
++ *
++ * Opcode Encoding. muli is identified by its OP value. Then OPX & 0x02
++ * is used to differentiate between the division opcodes and the remaining
++ * multiplication opcodes.
++ *
++ * Instruction OP OPX OPX & 0x02
++ * ----------- ---- ---- ----------
++ * muli 0x24
++ * divu 0x3a 0x24 0
++ * div 0x3a 0x25 0
++ * mul 0x3a 0x27 != 0
++ * mulxuu 0x3a 0x07 != 0
++ * mulxsu 0x3a 0x17 != 0
++ * mulxss 0x3a 0x1f != 0
++ */
++
++
++ /*
++ * Save everything on the stack to make it easy for the emulation routines
++ * to retrieve the source register operands.
++ */
++
++ addi sp, sp, -128
++ stw zero, 0(sp) // Save zero on stack to avoid special case for r0.
++ stw r1, 4(sp)
++ stw r2, 8(sp)
++ stw r3, 12(sp)
++ stw r4, 16(sp)
++ stw r5, 20(sp)
++ stw r6, 24(sp)
++ stw r7, 28(sp)
++ stw r8, 32(sp)
++ stw r9, 36(sp)
++ stw r10, 40(sp)
++ stw r11, 44(sp)
++ stw r12, 48(sp)
++ stw r13, 52(sp)
++ stw r14, 56(sp)
++ stw r15, 60(sp)
++ stw r16, 64(sp)
++ stw r17, 68(sp)
++ stw r18, 72(sp)
++ stw r19, 76(sp)
++ stw r20, 80(sp)
++ stw r21, 84(sp)
++ stw r22, 88(sp)
++ stw r23, 92(sp)
++ // Don't bother to save et. It's already been changed.
++ stw bt, 100(sp)
++ stw gp, 104(sp)
++ stw sp, 108(sp)
++ stw fp, 112(sp)
++ // Don't bother to save ea. It's already been changed.
++ stw ba, 120(sp)
++ stw ra, 124(sp)
++
++
++ /*
++ * Split the instruction into its fields. We need 4*A, 4*B, and 4*C as
++ * offsets to the stack pointer for access to the stored register values.
++ */
++ ldw r2,-4(ea) // r2 = AAAAA,BBBBB,IIIIIIIIIIIIIIII,PPPPPP
++ roli r3,r2,7 // r3 = BBB,IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BB
++ roli r4,r3,3 // r4 = IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB
++ roli r5,r4,2 // r5 = IIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB,II
++ srai r4,r4,16 // r4 = (sign-extended) IMM16
++ roli r6,r5,5 // r6 = XXXX,NNNNN,PPPPPP,AAAAA,BBBBB,CCCCC,XX
++ andi r2,r2,0x3f // r2 = 00000000000000000000000000,PPPPPP
++ andi r3,r3,0x7c // r3 = 0000000000000000000000000,AAAAA,00
++ andi r5,r5,0x7c // r5 = 0000000000000000000000000,BBBBB,00
++ andi r6,r6,0x7c // r6 = 0000000000000000000000000,CCCCC,00
++
++ /* Now
++ * r2 = OP
++ * r3 = 4*A
++ * r4 = IMM16 (sign extended)
++ * r5 = 4*B
++ * r6 = 4*C
++ */
++
++
++ /*
++ * Get the operands.
++ *
++ * It is necessary to check for muli because it uses an I-type instruction
++ * format, while the other instructions are have an R-type format.
++ *
++ * Prepare for either multiplication or division loop.
++ * They both loop 32 times.
++ */
++ movi r14,32
++
++ add r3,r3,sp // r3 = address of A-operand.
++ ldw r3,0(r3) // r3 = A-operand.
++ movi r7,0x24 // muli opcode (I-type instruction format)
++ beq r2,r7,mul_immed // muli doesn't use the B register as a source
++
++ add r5,r5,sp // r5 = address of B-operand.
++ ldw r5,0(r5) // r5 = B-operand.
++ // r4 = SSSSSSSSSSSSSSSS,-----IMM16------
++ // IMM16 not needed, align OPX portion
++ // r4 = SSSSSSSSSSSSSSSS,CCCCC,-OPX--,00000
++ srli r4,r4,5 // r4 = 00000,SSSSSSSSSSSSSSSS,CCCCC,-OPX--
++ andi r4,r4,0x3f // r4 = 00000000000000000000000000,-OPX--
++
++ /* Now
++ * r2 = OP
++ * r3 = src1
++ * r5 = src2
++ * r4 = OPX (no longer can be muli)
++ * r6 = 4*C
++ */
++
++
++
++ /*
++ * Multiply or Divide?
++ */
++ andi r7,r4,0x02 // For R-type multiply instructions, OPX & 0x02 != 0
++ bne r7,zero,multiply
++
++
++ /* DIVISION
++ *
++ * Divide an unsigned dividend by an unsigned divisor using
++ * a shift-and-subtract algorithm. The example below shows
++ * 43 div 7 = 6 for 8-bit integers. This classic algorithm uses a
++ * single register to store both the dividend and the quotient,
++ * allowing both values to be shifted with a single instruction.
++ *
++ * remainder dividend:quotient
++ * --------- -----------------
++ * initialize 00000000 00101011:
++ * shift 00000000 0101011:_
++ * remainder >= divisor? no 00000000 0101011:0
++ * shift 00000000 101011:0_
++ * remainder >= divisor? no 00000000 101011:00
++ * shift 00000001 01011:00_
++ * remainder >= divisor? no 00000001 01011:000
++ * shift 00000010 1011:000_
++ * remainder >= divisor? no 00000010 1011:0000
++ * shift 00000101 011:0000_
++ * remainder >= divisor? no 00000101 011:00000
++ * shift 00001010 11:00000_
++ * remainder >= divisor? yes 00001010 11:000001
++ * remainder -= divisor - 00000111
++ * ----------
++ * 00000011 11:000001
++ * shift 00000111 1:000001_
++ * remainder >= divisor? yes 00000111 1:0000011
++ * remainder -= divisor - 00000111
++ * ----------
++ * 00000000 1:0000011
++ * shift 00000001 :0000011_
++ * remainder >= divisor? no 00000001 :00000110
++ *
++ * The quotient is 00000110.
++ */
++
++divide:
++ /*
++ * Prepare for division by assuming the result
++ * is unsigned, and storing its "sign" as 0.
++ */
++ movi r17,0
++
++
++ // Which division opcode?
++ xori r7,r4,0x25 // OPX of div
++ bne r7,zero,unsigned_division
++
++
++ /*
++ * OPX is div. Determine and store the sign of the quotient.
++ * Then take the absolute value of both operands.
++ */
++ xor r17,r3,r5 // MSB contains sign of quotient
++ bge r3,zero,dividend_is_nonnegative
++ sub r3,zero,r3 // -r3
++dividend_is_nonnegative:
++ bge r5,zero,divisor_is_nonnegative
++ sub r5,zero,r5 // -r5
++divisor_is_nonnegative:
++
++
++unsigned_division:
++ // Initialize the unsigned-division loop.
++ movi r13,0 // remainder = 0
++
++ /* Now
++ * r3 = dividend : quotient
++ * r4 = 0x25 for div, 0x24 for divu
++ * r5 = divisor
++ * r13 = remainder
++ * r14 = loop counter (already initialized to 32)
++ * r17 = MSB contains sign of quotient
++ */
++
++
++ /*
++ * for (count = 32; count > 0; --count)
++ * {
++ */
++divide_loop:
++
++ /*
++ * Division:
++ *
++ * (remainder:dividend:quotient) <<= 1;
++ */
++ slli r13,r13,1
++ cmplt r7,r3,zero // r7 = MSB of r3
++ or r13,r13,r7
++ slli r3,r3,1
++
++
++ /*
++ * if (remainder >= divisor)
++ * {
++ * set LSB of quotient
++ * remainder -= divisor;
++ * }
++ */
++ bltu r13,r5,div_skip
++ ori r3,r3,1
++ sub r13,r13,r5
++div_skip:
++
++ /*
++ * }
++ */
++ subi r14,r14,1
++ bne r14,zero,divide_loop
++
++
++ /* Now
++ * r3 = quotient
++ * r4 = 0x25 for div, 0x24 for divu
++ * r6 = 4*C
++ * r17 = MSB contains sign of quotient
++ */
++
++
++ /*
++ * Conditionally negate signed quotient. If quotient is unsigned,
++ * the sign already is initialized to 0.
++ */
++ bge r17,zero,quotient_is_nonnegative
++ sub r3,zero,r3 // -r3
++quotient_is_nonnegative:
++
++
++ /*
++ * Final quotient is in r3.
++ */
++ add r6,r6,sp
++ stw r3,0(r6) // write quotient to stack
++ br restore_registers
++
++
++
++
++ /* MULTIPLICATION
++ *
++ * A "product" is the number that one gets by summing a "multiplicand"
++ * several times. The "multiplier" specifies the number of copies of the
++ * multiplicand that are summed.
++ *
++ * Actual multiplication algorithms don't use repeated addition, however.
++ * Shift-and-add algorithms get the same answer as repeated addition, and
++ * they are faster. To compute the lower half of a product (pppp below)
++ * one shifts the product left before adding in each of the partial products
++ * (a * mmmm) through (d * mmmm).
++ *
++ * To compute the upper half of a product (PPPP below), one adds in the
++ * partial products (d * mmmm) through (a * mmmm), each time following the
++ * add by a right shift of the product.
++ *
++ * mmmm
++ * * abcd
++ * ------
++ * #### = d * mmmm
++ * #### = c * mmmm
++ * #### = b * mmmm
++ * #### = a * mmmm
++ * --------
++ * PPPPpppp
++ *
++ * The example above shows 4 partial products. Computing actual Nios II
++ * products requires 32 partials.
++ *
++ * It is possible to compute the result of mulxsu from the result of mulxuu
++ * because the only difference between the results of these two opcodes is
++ * the value of the partial product associated with the sign bit of rA.
++ *
++ * mulxsu = mulxuu - (rA < 0) ? rB : 0;
++ *
++ * It is possible to compute the result of mulxss from the result of mulxsu
++ * because the only difference between the results of these two opcodes is
++ * the value of the partial product associated with the sign bit of rB.
++ *
++ * mulxss = mulxsu - (rB < 0) ? rA : 0;
++ *
++ */
++
++mul_immed:
++ // Opcode is muli. Change it into mul for remainder of algorithm.
++ mov r6,r5 // Field B is dest register, not field C.
++ mov r5,r4 // Field IMM16 is src2, not field B.
++ movi r4,0x27 // OPX of mul is 0x27
++
++multiply:
++ // Initialize the multiplication loop.
++ movi r9,0 // mul_product = 0
++ movi r10,0 // mulxuu_product = 0
++ mov r11,r5 // save original multiplier for mulxsu and mulxss
++ mov r12,r5 // mulxuu_multiplier (will be shifted)
++ movi r16,1 // used to create "rori B,A,1" from "ror B,A,r16"
++
++ /* Now
++ * r3 = multiplicand
++ * r5 = mul_multiplier
++ * r6 = 4 * dest_register (used later as offset to sp)
++ * r7 = temp
++ * r9 = mul_product
++ * r10 = mulxuu_product
++ * r11 = original multiplier
++ * r12 = mulxuu_multiplier
++ * r14 = loop counter (already initialized)
++ * r16 = 1
++ */
++
++
++ /*
++ * for (count = 32; count > 0; --count)
++ * {
++ */
++multiply_loop:
++
++ /*
++ * mul_product <<= 1;
++ * lsb = multiplier & 1;
++ */
++ slli r9,r9,1
++ andi r7,r12,1
++
++ /*
++ * if (lsb == 1)
++ * {
++ * mulxuu_product += multiplicand;
++ * }
++ */
++ beq r7,zero,mulx_skip
++ add r10,r10,r3
++ cmpltu r7,r10,r3 // Save the carry from the MSB of mulxuu_product.
++ ror r7,r7,r16 // r7 = 0x80000000 on carry, or else 0x00000000
++mulx_skip:
++
++ /*
++ * if (MSB of mul_multiplier == 1)
++ * {
++ * mul_product += multiplicand;
++ * }
++ */
++ bge r5,zero,mul_skip
++ add r9,r9,r3
++mul_skip:
++
++ /*
++ * mulxuu_product >>= 1; logical shift
++ * mul_multiplier <<= 1; done with MSB
++ * mulx_multiplier >>= 1; done with LSB
++ */
++ srli r10,r10,1
++ or r10,r10,r7 // OR in the saved carry bit.
++ slli r5,r5,1
++ srli r12,r12,1
++
++
++ /*
++ * }
++ */
++ subi r14,r14,1
++ bne r14,zero,multiply_loop
++
++
++ /*
++ * Multiply emulation loop done.
++ */
++
++ /* Now
++ * r3 = multiplicand
++ * r4 = OPX
++ * r6 = 4 * dest_register (used later as offset to sp)
++ * r7 = temp
++ * r9 = mul_product
++ * r10 = mulxuu_product
++ * r11 = original multiplier
++ */
++
++
++ // Calculate address for result from 4 * dest_register
++ add r6,r6,sp
++
++
++ /*
++ * Select/compute the result based on OPX.
++ */
++
++
++ // OPX == mul? Then store.
++ xori r7,r4,0x27
++ beq r7,zero,store_product
++
++ // It's one of the mulx.. opcodes. Move over the result.
++ mov r9,r10
++
++ // OPX == mulxuu? Then store.
++ xori r7,r4,0x07
++ beq r7,zero,store_product
++
++ // Compute mulxsu
++ //
++ // mulxsu = mulxuu - (rA < 0) ? rB : 0;
++ //
++ bge r3,zero,mulxsu_skip
++ sub r9,r9,r11
++mulxsu_skip:
++
++ // OPX == mulxsu? Then store.
++ xori r7,r4,0x17
++ beq r7,zero,store_product
++
++ // Compute mulxss
++ //
++ // mulxss = mulxsu - (rB < 0) ? rA : 0;
++ //
++ bge r11,zero,mulxss_skip
++ sub r9,r9,r3
++mulxss_skip:
++ // At this point, assume that OPX is mulxss, so store
++
++
++store_product:
++ stw r9,0(r6)
++
++
++restore_registers:
++ // No need to restore r0.
++ ldw r1, 4(sp)
++ ldw r2, 8(sp)
++ ldw r3, 12(sp)
++ ldw r4, 16(sp)
++ ldw r5, 20(sp)
++ ldw r6, 24(sp)
++ ldw r7, 28(sp)
++ ldw r8, 32(sp)
++ ldw r9, 36(sp)
++ ldw r10, 40(sp)
++ ldw r11, 44(sp)
++ ldw r12, 48(sp)
++ ldw r13, 52(sp)
++ ldw r14, 56(sp)
++ ldw r15, 60(sp)
++ ldw r16, 64(sp)
++ ldw r17, 68(sp)
++ ldw r18, 72(sp)
++ ldw r19, 76(sp)
++ ldw r20, 80(sp)
++ ldw r21, 84(sp)
++ ldw r22, 88(sp)
++ ldw r23, 92(sp)
++ ldw et, 96(sp)
++ ldw bt, 100(sp)
++ ldw gp, 104(sp)
++ // Don't corrupt sp.
++ ldw fp, 112(sp)
++ // Don't corrupt ea.
++ ldw ba, 120(sp)
++ ldw ra, 124(sp)
++ addi sp, sp, 128
++ eret
++
++.set at
++.set break
++
+diff --git a/arch/nios2nommu/kernel/head.S b/arch/nios2nommu/kernel/head.S
+new file mode 100644
+index 0000000..f1cba65
+--- /dev/null
++++ b/arch/nios2nommu/kernel/head.S
+@@ -0,0 +1,228 @@
++/*
++ * head.S for Altera's Excalibur development board with nios processor
++ *
++ * (c) Vic Phillips, Microtronix Datacom Ltd., 2001
++ * (C) Copyright 2004 Microtronix Datacom Ltd
++ *
++ * Based on the following from the Excalibur sdk distribution:
++ * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
++ *
++ * 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 <asm/asm-offsets.h>
++#include <asm/asm-macros.h>
++
++
++#ifdef CONFIG_CRC_CHECK
++/**********************************************/
++/* Define where the CRC table lives in flash. */
++/* The __CRC_Sector_Size is the flash sector */
++/* size for the address range. */
++/**********************************************/
++
++ GEQU __CRC_Table_Begin,(na_flash)+0x4000 /* Second sector of main board flash */
++ GEQU __CRC_Sector_Size,0x2000
++#endif
++
++/*
++ * This global variable is used as an extension to the nios'
++ * STATUS register to emulate a user/supervisor mode.
++ */
++ .data
++ .align 2
++ .set noat
++ .global status_extension
++status_extension:
++ .long 0
++
++ .global _current_thread
++_current_thread:
++ .long 0
++/*
++ * Input(s): passed from u-boot
++ * r4 - Optional pointer to a board information structure.
++ * r5 - Optional pointer to the physical starting address of the init RAM
++ * disk.
++ * r6 - Optional pointer to the physical ending address of the init RAM
++ * disk.
++ * r7 - Optional pointer to the physical starting address of any kernel
++ * command-line parameters.
++ */
++
++/*
++ * First executable code - detected and jumped to by the ROM bootstrap
++ * if the code resides in flash (looks for "Nios" at offset 0x0c from
++ * the potential executable image).
++ */
++ .text
++ .global _start
++_start:
++ wrctl status,r0 /* Disable interrupts */
++
++ /* Flush all cache lines within the instruction cache */
++
++ movia r1,NIOS2_ICACHE_SIZE
++ movui r2,NIOS2_ICACHE_LINE_SIZE
++
++text_flush:
++ flushi r1
++ sub r1,r1,r2
++ bgt r1,r0,text_flush
++ br 1f
++
++ /* This is the default location for the exception
++ * handler. Code in jump to our handler
++ */
++
++ movia r24,inthandler
++ jmp r24
++1:
++ /*
++ * After flushing the instruction cache, we must flush the data
++ * cache.
++ */
++
++ movia r1,NIOS2_DCACHE_SIZE
++ movi r2,NIOS2_DCACHE_LINE_SIZE
++
++data_flush:
++ flushd 0(r1)
++ sub r1,r1,r2
++ bgt r1,r0,data_flush
++
++NR_MoveStart:
++#ifdef CONFIG_BREAK_ON_START
++ break
++#endif //CONFIG_BREAK_ON_START
++ nextpc r1 /* Find out where we are */
++chkadr:
++ movia r2,chkadr
++ beq r1,r2,finish_move /* We are running in RAM done */
++ addi r1,r1,(_start - chkadr) /* Source */
++ movia r2,_start /* Destination */
++ movia r3,__bss_start /* End of copy */
++
++loop_move: // r1: src, r2: dest, r3: last dest
++ ldw r8,0(r1) // load a word from [r1]
++ stw r8,0(r2) // stort a word to dest [r2]
++ flushd 0(r2) // Flush cache for safty
++ addi r1,r1,4 // inc the src addr
++ addi r2,r2,4 // inc the dest addr
++ blt r2,r3,loop_move
++
++ movia r1,finish_move // VMA(_start)->l1
++ jmp r1 // jmp to _start
++
++finish_move:
++
++ //------------------------------------
++ // Disable interrupts on known devices
++ //
++#ifdef NA_ENET_ASM
++#ifdef NA_ENET_RESET_ASM
++ movia r1,NA_ENET_RESET_ASM // ethernet reset address
++ stwio r0,0(r1) // reset
++#endif
++#ifdef NA_ENET_RESET_N_ASM
++ movia r1,NA_ENET_RESET_N_ASM // ethernet reset address
++ stwio r0,0(r1) // reset
++#endif
++ nop // give it some time
++ nop //
++ nop //
++ nop //
++#endif
++#ifdef NA_TIMER0_ASM
++ movia r1,NA_TIMER0_ASM // get timer address
++ stwio r0,NP_TIMERCONTROL_ASM(r1) // clear interrupt enable
++ stwio r0,NP_TIMERSTATUS_ASM(r1) // clear interrupt condition
++#endif
++#ifdef NA_UART0_ASM
++ movia r1,NA_UART0_ASM
++ stwio r0,NP_UARTCONTROL_ASM(r1) // clear interrupt enable
++ stwio r0,NP_UARTSTATUS_ASM(r1) // clear interrupt status
++#endif
++#ifdef NA_UART1_ASM
++ movia r1,NA_UART1_ASM
++ stwio r0,NP_UARTCONTROL_ASM(r1) // clear interrupt enable
++ stwio r0,NP_UARTSTATUS_ASM(r1) // clear interrupt status
++#endif
++#ifdef NA_UART2_ASM
++ movia r1,NA_UART2_ASM
++ stwio r0,NP_UARTCONTROL_ASM(r1) // clear interrupt enable
++ stwio r0,NP_UARTSTATUS_ASM(r1) // clear interrupt status
++#endif
++#ifdef NA_UART3_ASM
++ movia r1,NA_UART3_ASM
++ stwio r0,NP_UARTCONTROL_ASM(r1) // clear interrupt enable
++ stwio r0,NP_UARTSTATUS_ASM(r1) // clear interrupt status
++#endif
++#ifdef NA_IDE_INTERFACE_ASM
++ movia r1,NA_IDE_INTERFACE_ASM // ATA reset
++ stwio r0,0(r1) // write to control register
++#endif
++#ifdef NA_ENET_ASM
++#ifdef NA_ENET_RESET_ASM
++ movia r1,NA_ENET_RESET_ASM // ethernet reset address
++ movui r2,1 // reset
++ stwio r2,0(r1) //
++#endif
++#ifdef NA_ENET_RESET_N_ASM
++ movia r1,NA_ENET_RESET_N_ASM // ethernet reset address
++ movui r2,1 // reset
++ stwio r2,0(r1) //
++#endif
++#endif
++ wrctl ienable,r0 // Mask off all possible interrupts
++
++ //------------------------------------------------------
++ // Zero out the .bss segment (uninitialized common data)
++ //
++ movia r2,__bss_start // presume nothing is between
++ movia r1,_end // the .bss and _end.
++1:
++ stb r0,0(r2)
++ addi r2,r2,1
++ bne r1,r2,1b
++
++ //------------------------------------------------------
++ // Call main() with interrupts disabled
++ //
++ movia r1,status_extension // get the STATUS extension address
++ movi r2,PS_S_ASM // set initial mode = supervisor
++ stw r2,0(r1)
++
++ movia r1,init_thread_union // set stack at top of the task union
++ addi sp,r1,THREAD_SIZE_ASM
++ movia r2,_current_thread // Remember current thread
++ stw r1,0(r2)
++
++ movia r1,nios2_boot_init // save args r4-r7 passed from u-boot
++ callr r1
++
++ movia r1,main // call main as a subroutine
++ callr r1
++
++ //------------------------------------------------------------------
++ // If we return from main, break to the oci debugger and buggered we are
++ //
++ break
++
++ /* End of startup code */
++.set at
++
++
+diff --git a/arch/nios2nommu/kernel/init_task.c b/arch/nios2nommu/kernel/init_task.c
+new file mode 100644
+index 0000000..867e8fb
+--- /dev/null
++++ b/arch/nios2nommu/kernel/init_task.c
+@@ -0,0 +1,69 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/init_task.c
++ *
++ * Ported from arch/m68knommu/kernel/init_task.c
++ *
++ * Copyright (C) 2003, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/init_task.h>
++#include <linux/fs.h>
++#include <linux/mqueue.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++static struct fs_struct init_fs = INIT_FS;
++static struct files_struct init_files = INIT_FILES;
++static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
++static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
++struct mm_struct init_mm = INIT_MM(init_mm);
++
++EXPORT_SYMBOL(init_mm);
++
++/*
++ * Initial task structure.
++ *
++ * All other task structs will be allocated on slabs in fork.c
++ */
++__asm__(".align 2");
++struct task_struct init_task = INIT_TASK(init_task);
++
++
++/*
++ * Initial thread structure.
++ *
++ * We need to make sure that this is 8192-byte aligned due to the
++ * way process stacks are handled. This is done by having a special
++ * "init_task" linker map entry..
++ */
++union thread_union init_thread_union
++ __attribute__((__section__(".data.init_task"))) =
++ { INIT_THREAD_INFO(init_task) };
++
+diff --git a/arch/nios2nommu/kernel/io.c b/arch/nios2nommu/kernel/io.c
+new file mode 100644
+index 0000000..e1b0b12
+--- /dev/null
++++ b/arch/nios2nommu/kernel/io.c
+@@ -0,0 +1,143 @@
++/*--------------------------------------------------------------------
++ *
++ * Optimized IO string functions.
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/io.h>
++
++void insl(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned long read32;
++
++ if ((unsigned long)dst & 2){
++ /* Unaligned destination pointer, need to do
++ * two 16 bit writes for each read.
++ */
++ unsigned short *p=(unsigned short*)dst;
++ while (count--){
++ read32 = inl(port);
++ *p++ = read32 & 0xFFFF;
++ *p++ = read32 >> 16;
++ }
++ }
++ else {
++ unsigned long *p=(unsigned long*)dst;
++ while (count--)
++ *p++ = inl(port);
++ }
++}
++
++void insw(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned long dst1=(unsigned long)dst;
++ if (count > 8) {
++ /* Long word align buffer ptr */
++ if (dst1 & 2) {
++ *(unsigned short*)dst1 = inw(port);
++ dst1 += sizeof(unsigned short);
++ count--;
++ }
++
++ /* Input pairs of short and store as longs */
++ while (count >= 8) {
++ *((unsigned long *)dst1) = inw(port) + (inw(port) << 16); dst1+=sizeof(unsigned long);
++ *((unsigned long *)dst1) = inw(port) + (inw(port) << 16); dst1+=sizeof(unsigned long);
++ *((unsigned long *)dst1) = inw(port) + (inw(port) << 16); dst1+=sizeof(unsigned long);
++ *((unsigned long *)dst1) = inw(port) + (inw(port) << 16); dst1+=sizeof(unsigned long);
++ count -= 8;
++ }
++ }
++
++ /* Input remaining shorts */
++ while (count--) {
++ *((unsigned short *)dst1) = inw(port);
++ dst1 += sizeof(unsigned short);
++ }
++}
++
++
++void outsl(unsigned long port, void *src, unsigned long count)
++{
++ unsigned long src1=(unsigned long)src;
++ unsigned long write32;
++
++ if (src1 & 2){
++ /* Unaligned source pointer, need to read
++ * two 16 bit shorts before writing to register.
++ */
++ while (count--){
++ write32 = *(unsigned short *)src1;
++ src1+=sizeof(unsigned short);
++ write32 |= *((unsigned short *)src1) << 16;
++ src1+=sizeof(unsigned short);
++ outl(write32,port);
++ }
++ }
++ else {
++ while (count--) {
++ outl(*(unsigned long *)src1,port);
++ src1+=sizeof(unsigned long);
++ }
++ }
++}
++
++void outsw(unsigned long port, void *src, unsigned long count)
++{
++ unsigned int lw;
++ unsigned long src1=(unsigned long)src;
++
++ if (count > 8) {
++ /* Long word align buffer ptr */
++ if (src1 & 2) {
++ outw( *(unsigned short *)src1, port );
++ count--;
++ src1 += sizeof(unsigned short);
++ }
++
++ /* Read long words and output as pairs of short */
++ while (count >= 8) {
++ lw = *(unsigned long *)src1;
++ src1+=sizeof(unsigned long);
++ outw(lw, port);
++ outw((lw >> 16), port);
++ lw = *(unsigned long *)src1;
++ src1+=sizeof(unsigned long);
++ outw(lw, port);
++ outw((lw >> 16), port);
++ lw = *(unsigned long *)src1;
++ src1+=sizeof(unsigned long);
++ outw(lw, port);
++ outw((lw >> 16), port);
++ lw = *(unsigned long *)src1;
++ src1+=sizeof(unsigned long);
++ outw(lw, port);
++ outw((lw >> 16), port);
++ count -= 8;
++ }
++ }
++
++ /* Output remaining shorts */
++ while (count--) {
++ outw( *(unsigned short *)src1, port );
++ src1 += sizeof(unsigned short);
++ }
++}
+diff --git a/arch/nios2nommu/kernel/irq.c b/arch/nios2nommu/kernel/irq.c
+new file mode 100644
+index 0000000..f1b2347
+--- /dev/null
++++ b/arch/nios2nommu/kernel/irq.c
+@@ -0,0 +1,245 @@
++/*
++ * linux/arch/$(ARCH)/irq.c -- general exception handling code
++ *
++ * Cloned from Linux/m68k.
++ *
++ * No original Copyright holder listed,
++ * Probabily original (C) Roman Zippel (assigned DJD, 1999)
++ *
++ * Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive
++ * for more details.
++ */
++
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/kernel_stat.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/seq_file.h>
++
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/page.h>
++#include <asm/nios.h>
++#include <asm/hardirq.h>
++
++/* table for system interrupt handlers */
++irq_hand_t irq_list[NR_IRQS];
++
++/* The number of spurious interrupts */
++volatile unsigned int num_spurious;
++
++#define NUM_IRQ_NODES 16
++static irq_node_t nodes[NUM_IRQ_NODES];
++
++void __init init_irq_proc(void)
++{
++ /* Insert /proc/irq driver here */
++}
++
++static irqreturn_t default_irq_handler(int irq, void *ptr)
++{
++#if 1
++ printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n",
++ __FILE__, __LINE__, irq, irq);
++#endif
++ disable_irq(irq);
++ return(IRQ_NONE);
++}
++
++/*
++ * void init_IRQ(void)
++ *
++ * Parameters: None
++ *
++ * Returns: Nothing
++ *
++ * This function should be called during kernel startup to initialize
++ * the IRQ handling routines.
++ */
++
++void __init init_IRQ(void)
++{
++ int i;
++
++ for (i = 0; i < NR_IRQS; i++) {
++ irq_list[i].handler = default_irq_handler;
++ irq_list[i].flags = IRQ_FLG_STD;
++ irq_list[i].dev_id = NULL;
++ irq_list[i].devname = NULL;
++ }
++
++ for (i = 0; i < NUM_IRQ_NODES; i++)
++ nodes[i].handler = NULL;
++
++ /* turn off all interrupts */
++ clrimr(0);
++
++#ifdef DEBUG
++ printk("init_IRQ done\n");
++#endif
++}
++
++irq_node_t *new_irq_node(void)
++{
++ irq_node_t *node;
++ short i;
++
++ for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
++ if (!node->handler)
++ return node;
++
++ printk (KERN_INFO "new_irq_node: out of nodes\n");
++ return NULL;
++}
++
++int request_irq(unsigned int irq,
++ irq_handler_t handler,
++ unsigned long flags,
++ const char *devname,
++ void *dev_id)
++{
++ if (irq >= NR_IRQS) {
++ printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
++ return -ENXIO;
++ }
++
++ if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
++ if (irq_list[irq].flags & IRQ_FLG_LOCK) {
++ printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n",
++ __FUNCTION__, irq, irq_list[irq].devname);
++ return -EBUSY;
++ }
++ if (flags & IRQ_FLG_REPLACE) {
++ printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n",
++ __FUNCTION__, devname, irq, irq_list[irq].devname);
++ return -EBUSY;
++ }
++ }
++ irq_list[irq].handler = handler;
++ irq_list[irq].flags = flags;
++ irq_list[irq].dev_id = dev_id;
++ irq_list[irq].devname = devname;
++
++ setimr(1<<irq);
++
++ return 0;
++}
++
++void free_irq(unsigned int irq, void *dev_id)
++{
++ if (irq >= NR_IRQS) {
++ printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
++ return;
++ }
++
++ if (irq_list[irq].dev_id != dev_id)
++ printk(KERN_ERR "%s: Removing probably wrong IRQ %d from %s\n",
++ __FUNCTION__, irq, irq_list[irq].devname);
++
++ irq_list[irq].handler = default_irq_handler;
++ irq_list[irq].flags = IRQ_FLG_STD;
++ irq_list[irq].dev_id = NULL;
++ irq_list[irq].devname = NULL;
++
++ clrimr(~(1<<irq));
++}
++
++/* usually not useful in embedded systems */
++unsigned long probe_irq_on (void)
++{
++ return 0;
++}
++
++int probe_irq_off (unsigned long irqs)
++{
++ return 0;
++}
++
++void enable_irq(unsigned int irq)
++{
++ setimr(1<<irq);
++}
++
++void disable_irq(unsigned int irq)
++{
++ clrimr(~(1<<irq));
++}
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++ int i = *(loff_t *) v;
++
++ if (i == 0) {
++ seq_printf(p, " : %10u spurious\n", num_spurious);
++ }
++
++ if ((i < NR_IRQS) && (!(irq_list[i].flags & IRQ_FLG_STD))) {
++ seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]);
++ if (irq_list[i].flags & IRQ_FLG_LOCK)
++ seq_printf(p, "L ");
++ else
++ seq_printf(p, " ");
++ seq_printf(p, "%s\n", irq_list[i].devname);
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_PREEMPT_TIMES
++extern void latency_cause(int,int);
++#else
++#define latency_cause(a, b)
++#endif
++asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
++{
++
++ /* give the machine specific code a crack at it first */
++ irq_enter();
++ kstat_cpu(0).irqs[vec]++;
++ latency_cause(-99,~vec);
++
++ if (irq_list[vec].handler) {
++ if ((irq_list[vec].handler(vec, irq_list[vec].dev_id))==IRQ_NONE)
++ ;
++ } else
++#ifdef DEBUG
++ {
++ printk(KERN_ERR "No interrupt handler for level %ld\n", vec);
++//// asm("trap 5");
++ }
++#else
++ #if 1
++ printk(KERN_ERR "Ignoring interrupt %ld: no handler\n", vec);
++ #else
++ panic("No interrupt handler for level %ld\n", vec);
++ #endif
++#endif
++
++ irq_exit();
++}
++
++int get_irq_list(char *buf)
++{
++ int i, len = 0;
++
++ /* autovector interrupts */
++ for (i = 0; i < NR_IRQS; i++) {
++ if (irq_list[i].handler) {
++ len += sprintf(buf+len, "auto %2d: %10u ", i,
++ i ? kstat_cpu(0).irqs[i] : num_spurious);
++ if (irq_list[i].flags & IRQ_FLG_LOCK)
++ len += sprintf(buf+len, "L ");
++ else
++ len += sprintf(buf+len, " ");
++ len += sprintf(buf+len, "%s\n", irq_list[i].devname);
++ }
++ }
++ return len;
++}
++EXPORT_SYMBOL(request_irq);
++EXPORT_SYMBOL(free_irq);
+diff --git a/arch/nios2nommu/kernel/module.c b/arch/nios2nommu/kernel/module.c
+new file mode 100644
+index 0000000..99b270f
+--- /dev/null
++++ b/arch/nios2nommu/kernel/module.c
+@@ -0,0 +1,173 @@
++/* Kernel module help for Nios2.
++ Copyright (C) 2004 Microtronix Datacom Ltd.
++ Copyright (C) 2001,03 Rusty Russell
++
++ 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
++
++ Written by Wentao Xu <xuwentao@microtronix.com>
++*/
++#include <linux/moduleloader.h>
++#include <linux/elf.h>
++#include <linux/vmalloc.h>
++#include <linux/fs.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(fmt , ...)
++#endif
++
++void *module_alloc(unsigned long size)
++{
++ if (size == 0)
++ return NULL;
++ return vmalloc(size);
++}
++
++
++/* Free memory returned from module_alloc */
++void module_free(struct module *mod, void *module_region)
++{
++ vfree(module_region);
++ /* FIXME: If module_region == mod->init_region, trim exception
++ table entries. */
++}
++
++/* We don't need anything special. */
++int module_frob_arch_sections(Elf_Ehdr *hdr,
++ Elf_Shdr *sechdrs,
++ char *secstrings,
++ struct module *mod)
++{
++ return 0;
++}
++
++int apply_relocate(Elf32_Shdr *sechdrs,
++ const char *strtab,
++ unsigned int symindex,
++ unsigned int relsec,
++ struct module *me)
++{
++ printk(KERN_ERR "module %s: NO-ADD RELOCATION unsupported\n",
++ me->name);
++ return -ENOEXEC;
++}
++
++
++int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
++ unsigned int symindex, unsigned int relsec,
++ struct module *mod)
++{
++ unsigned int i;
++ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
++
++ DEBUGP ("Applying relocate section %u to %u\n", relsec,
++ sechdrs[relsec].sh_info);
++
++ for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
++ /* This is where to make the change */
++ uint32_t word;
++ uint32_t *loc
++ = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
++ + rela[i].r_offset);
++ /* This is the symbol it is referring to. Note that all
++ undefined symbols have been resolved. */
++ Elf32_Sym *sym
++ = ((Elf32_Sym *)sechdrs[symindex].sh_addr
++ + ELF32_R_SYM (rela[i].r_info));
++ uint32_t v = sym->st_value + rela[i].r_addend;
++
++ switch (ELF32_R_TYPE (rela[i].r_info)) {
++ case R_NIOS2_NONE:
++ break;
++
++ case R_NIOS2_BFD_RELOC_32:
++ *loc += v;
++ break;
++
++ case R_NIOS2_PCREL16:
++ v -= (uint32_t)loc + 4;
++ if ((int32_t)v > 0x7fff ||
++ (int32_t)v < -(int32_t)0x8000) {
++ printk(KERN_ERR
++ "module %s: relocation overflow\n",
++ mod->name);
++ return -ENOEXEC;
++ }
++ word = *loc;
++ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
++ break;
++
++ case R_NIOS2_CALL26:
++ if (v & 3) {
++ printk(KERN_ERR
++ "module %s: dangerous relocation\n",
++ mod->name);
++ return -ENOEXEC;
++ }
++ if ((v >> 28) != ((uint32_t)loc >> 28)) {
++ printk(KERN_ERR
++ "module %s: relocation overflow\n",
++ mod->name);
++ return -ENOEXEC;
++ }
++ *loc = (*loc & 0x3f) | ((v >> 2) << 6);
++ break;
++
++ case R_NIOS2_HI16:
++ word = *loc;
++ *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
++ (word & 0x3f);
++ break;
++
++ case R_NIOS2_LO16:
++ word = *loc;
++ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
++ (word & 0x3f);
++ break;
++
++ case R_NIOS2_HIADJ16:
++ {
++ Elf32_Addr word2;
++
++ word = *loc;
++ word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
++ *loc = ((((word >> 22) << 16) | word2) << 6) |
++ (word & 0x3f);
++ }
++ break;
++
++ default:
++ printk (KERN_ERR "module %s: Unknown reloc: %u\n",
++ mod->name, ELF32_R_TYPE (rela[i].r_info));
++ return -ENOEXEC;
++ }
++ }
++
++ return 0;
++}
++
++int module_finalize(const Elf_Ehdr *hdr,
++ const Elf_Shdr *sechdrs,
++ struct module *me)
++{
++ return 0;
++}
++
++void module_arch_cleanup(struct module *mod)
++{
++}
+diff --git a/arch/nios2nommu/kernel/nios2_ksyms.c b/arch/nios2nommu/kernel/nios2_ksyms.c
+new file mode 100644
+index 0000000..720f007
+--- /dev/null
++++ b/arch/nios2nommu/kernel/nios2_ksyms.c
+@@ -0,0 +1,113 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/nios_ksyms.c
++ *
++ * Derived from Nios1
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * vic - copied from v850
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++//;dgt2;tmp;
++
++#include <linux/module.h>
++#include <linux/linkage.h>
++#include <linux/sched.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/user.h>
++#include <linux/elfcore.h>
++#include <linux/in6.h>
++#include <linux/interrupt.h>
++
++#include <asm/setup.h>
++#include <asm/pgalloc.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/semaphore.h>
++#include <asm/checksum.h>
++#include <asm/hardirq.h>
++#include <asm/current.h>
++
++extern void dump_thread(struct pt_regs *, struct user *);
++/* platform dependent support */
++
++EXPORT_SYMBOL(__ioremap);
++EXPORT_SYMBOL(iounmap);
++EXPORT_SYMBOL(dump_fpu);
++EXPORT_SYMBOL(dump_thread);
++
++EXPORT_SYMBOL(kernel_thread);
++
++/* Networking helper routines. */
++EXPORT_SYMBOL(csum_partial_copy);
++
++EXPORT_SYMBOL(memcpy);
++EXPORT_SYMBOL(memset);
++EXPORT_SYMBOL(memmove);
++
++EXPORT_SYMBOL(__down);
++EXPORT_SYMBOL(__down_interruptible);
++EXPORT_SYMBOL(__down_trylock);
++EXPORT_SYMBOL(__up);
++
++EXPORT_SYMBOL(get_wchan);
++
++/*
++ * libgcc functions - functions that are used internally by the
++ * compiler... (prototypes are not correct though, but that
++ * doesn't really matter since they're not versioned).
++ */
++extern void __gcc_bcmp(void);
++extern void __ashldi3(void);
++extern void __ashrdi3(void);
++extern void __cmpdi2(void);
++extern void __divdi3(void);
++extern void __divsi3(void);
++extern void __lshrdi3(void);
++extern void __moddi3(void);
++extern void __modsi3(void);
++extern void __muldi3(void);
++extern void __mulsi3(void);
++extern void __negdi2(void);
++extern void __ucmpdi2(void);
++extern void __udivdi3(void);
++extern void __udivmoddi4(void);
++extern void __udivsi3(void);
++extern void __umoddi3(void);
++extern void __umodsi3(void);
++
++ /* gcc lib functions */
++EXPORT_SYMBOL(__gcc_bcmp);
++EXPORT_SYMBOL(__ashldi3);
++EXPORT_SYMBOL(__ashrdi3);
++EXPORT_SYMBOL(__cmpdi2);
++EXPORT_SYMBOL(__divdi3);
++EXPORT_SYMBOL(__divsi3);
++EXPORT_SYMBOL(__lshrdi3);
++EXPORT_SYMBOL(__moddi3);
++EXPORT_SYMBOL(__modsi3);
++EXPORT_SYMBOL(__muldi3);
++EXPORT_SYMBOL(__mulsi3);
++EXPORT_SYMBOL(__negdi2);
++EXPORT_SYMBOL(__ucmpdi2);
++EXPORT_SYMBOL(__udivdi3);
++EXPORT_SYMBOL(__udivmoddi4);
++EXPORT_SYMBOL(__udivsi3);
++EXPORT_SYMBOL(__umoddi3);
++EXPORT_SYMBOL(__umodsi3);
+diff --git a/arch/nios2nommu/kernel/nios_gdb_stub.c b/arch/nios2nommu/kernel/nios_gdb_stub.c
+new file mode 100644
+index 0000000..103925b
+--- /dev/null
++++ b/arch/nios2nommu/kernel/nios_gdb_stub.c
+@@ -0,0 +1,1456 @@
++// Modified for uClinux - Vic - Apr 2002
++// From:
++
++// File: nios_gdb_stub.c
++// Date: 2000 June 20
++// Author dvb \ Altera Santa Cruz
++
++#ifndef __KERNEL__
++#include "nios.h"
++#else
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <asm/nios.h>
++#endif
++
++#include "nios_gdb_stub.h"
++
++#define na_debug_peripheral_irq 8
++
++enum
++{
++ na_BreakpointTrap = 3,
++ na_SingleStepTrap = 4,
++ na_StartGDBTrap = 5
++};
++
++
++#ifdef __KERNEL__
++
++extern int _etext;
++
++static void puts( unsigned char *s )
++{
++ while(*s) {
++ while (!(nasys_printf_uart->np_uartstatus & np_uartstatus_trdy_mask));
++ nasys_printf_uart->np_uarttxdata = *s++;
++ }
++}
++
++#endif // __KERNEL__
++
++// --------------------------------
++// Local Prototypes
++
++#if GDB_DEBUG_PRINT
++
++static void StringFit(char *s,int w);
++
++// --------------------------------
++// Debugging The Debugger
++
++void GDB_RawMessage(char *s)
++ {
++ StringFit(s,32);
++ nr_pio_lcdwritescreen(s);
++ }
++#else
++ #define GDB_RawMessage(a,b,c) // define away to nothing
++#endif
++
++#if GDB_DEBUG_PRINT
++void GDB_Print2(char *s,int n1,int n2)
++ {
++ char st[1000];
++
++ sprintf(st,s,n1,n2);
++ GDB_RawMessage(st);
++ }
++#else
++ #define GDB_Print2(a,b,c) // define away to nothing
++#endif
++
++// If string is longer than w, cut out the middle.
++
++#if GDB_DEBUG_PRINT
++int StringLen(char *s)
++ {
++ int l = 0;
++
++ while(*s++)
++ l++;
++ return l;
++ }
++
++static void StringFit(char *s,int w)
++ {
++ if(StringLen(s) > w)
++ {
++ int i;
++
++
++ w = w / 2;
++
++ for(i = 0; i < w; i++)
++ {
++ s[i + w] = s[StringLen(s) - w + i];
++ }
++ s[w + w] = 0;
++ }
++ }
++#endif
++
++// ---------------------------------------------
++// Generic routines for dealing with
++// hex input, output, and parsing
++// (Adapted from other stubs.)
++
++NiosGDBGlobals gdb = {0}; // not static: the ISR uses it!
++
++static char dHexChars[16] = "0123456789abcdef";
++
++/*
++ * HexCharToValue -- convert a characters
++ * to its hex value, or -1 if not.
++ */
++char HexCharToValue(char c)
++{
++ char result=0;
++
++ if(c >= '0' && c <= '9')
++ result = c - '0';
++ else if(c >= 'a' && c <= 'f')
++ result = c - 'a' + 10;
++ else if(c >= 'A' && c <= 'F')
++ result = c - 'A' + 10;
++ else
++ result = -1;
++ return result;
++}
++
++/*
++ * HexStringToValue -- convert a 2*byte_width string of characters
++ * to its little endian hex value,
++ * or -1 if not.
++ * This routine is for strings of hex values
++ */
++unsigned long HexStringToValue(char *c, int byte_width)
++{
++ unsigned long result=0;
++ unsigned char a,b;
++ int i=0;
++
++ while (i < byte_width)
++ {
++ a = HexCharToValue(*c++);
++ if (a & 0x80) return a;
++ b = HexCharToValue(*c++);
++ if (b & 0x80) return b;
++ b = (a<<4) | (b&0x0f);
++ result |= b << (i*8);
++ i++;
++ }
++ return result;
++}
++
++/*
++ * Hex2Value -- convert a non-hex char delimited string
++ * to its big endian hex value.
++ * This routine is for address and byte count values
++ */
++
++char *Hex2Value(char *hexIn, int *valueOut)
++ {
++ char c;
++ int digitValue;
++ int value = 0;
++
++ while(1)
++ {
++ c = *hexIn;
++ digitValue = HexCharToValue(c);
++ if(digitValue < 0)
++ {
++ *valueOut = value;
++ return hexIn;
++ }
++ hexIn++;
++ value = (value << 4) + digitValue;
++ }
++ }
++
++/*
++ * HexToMem -- convert a string to a specified
++ * number of bytes in memory.
++ *
++ * JMB -- make this thing a bit smarter so
++ * that it selects the byte width to
++ * write based on the number of bytes
++ * and the destination address alignment.
++ * This is to support writes to non-byte enabled
++ * peripheral registers...I don't like it.
++ * Beware! there are cases where it wont work
++ */
++char *HexToMem(char *hexIn, char *memOut, int memByteCount)
++{
++ int i;
++ unsigned long x;
++ short *memOutS=0;
++ long *memOutL=0;
++ int byte_width;
++
++ //determine maximum byte width
++ if (((memByteCount%2) != 0) || (((unsigned int)memOut%2) != 0))
++ byte_width = 1;
++ else if (((memByteCount % 4) != 0) || (((unsigned int)memOut % 4) != 0))
++ {
++ byte_width = 2;
++ memOutS = (short *)memOut;
++ }
++ else
++ {
++ byte_width = 4;
++ memOutL = (long *)memOut;
++ }
++ for(i = 0; i < memByteCount; i+=byte_width)
++ {
++ x = HexStringToValue(hexIn,byte_width);
++ hexIn += byte_width*2;
++ switch (byte_width)
++ {
++ case 1:
++ *memOut++ = (unsigned char) 0x000000ff & x;
++ break;
++ case 2:
++ *memOutS++ = (unsigned short) 0x0000ffff & x;
++ break;
++ case 4:
++ *memOutL++ = x;
++ break;
++ default:
++ //How could this ever happen???
++ break;
++ }
++ }
++
++ return hexIn;
++}
++
++char *MemToHex(char *memIn, char *hexOut, int memByteCount)
++{
++ int i,j;
++ int byte_width;
++ unsigned long x=0;
++ unsigned short *memInS=0;
++ unsigned long *memInL=0;
++
++ //determine maximum byte width
++ if (((memByteCount % 2) != 0) || (((unsigned int)memIn % 2) != 0))
++ byte_width = 1;
++ else if (((memByteCount % 4) != 0) || (((unsigned int)memIn % 4) != 0))
++ {
++ byte_width = 2;
++ memInS = (short *)memIn;
++ }
++ else
++ {
++ byte_width = 4;
++ memInL = (long *)memIn;
++ }
++
++ for(i = 0; i < memByteCount; i+=byte_width)
++ {
++ switch (byte_width)
++ {
++ case 1:
++ x = *memIn++;
++ break;
++ case 2:
++ x = *memInS++;
++ break;
++ case 4:
++ x = *memInL++;
++ break;
++ default:
++ //How would we get here?
++ break;
++ }
++
++ for (j=0; j<byte_width; j++)
++ {
++ *hexOut++ = dHexChars[(x&0x000000f0)>>4];
++ *hexOut++ = dHexChars[x&0x0000000f];
++ x = x>>8;
++ }
++ }
++
++ *hexOut = 0;
++
++ return hexOut;
++}
++
++//Send just the + or - to indicate
++//ACK or NACK
++void GDBPutAck (char ack)
++{
++ if (gdb.comlink == ne_gdb_serial)
++ GDBPutChar (ack);
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ else
++ {
++ if (gdb.host_ip_address != 0)
++ nr_plugs_send_to (gdb.gdb_eth_plug, &ack, 1, 0,
++ gdb.host_ip_address,
++ gdb.host_port_number);
++ }
++#endif
++#endif
++}
++
++/*
++ * Once a $ comes in, use GetGDBPacket to
++ * retrieve a full gdb packet, and verify
++ * checksum, and reply + or -.
++ */
++int GetGDBPacket(char *aBuffer)
++{
++ int checksum=0;
++ int length=0;
++ char c;
++ int x=0;
++
++ if (gdb.comlink == ne_gdb_serial)
++ {
++ while ((c = GDBGetChar ()) != '$') ;
++
++startPacket:
++ length = 0;
++ checksum = 0;
++ while(((c = GDBGetChar()) != '#') && (length < kTextBufferSize))
++ {
++ if(c == '$')
++ goto startPacket;
++ checksum += c;
++ aBuffer[length++] = c;
++ aBuffer[length] = 0;
++ }
++
++ c = GDBGetChar();
++ x = HexCharToValue(c) << 4;
++ c = GDBGetChar();
++ x += HexCharToValue(c);
++
++
++ checksum &= 0xff;
++
++ GDB_Print2("GetPacket %d",length,0);
++ }
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ else
++ {
++ int srcidx;
++ // wait till beginning of packet
++ while (gdb.textBuffer[0] != '$') nr_plugs_idle();
++startEPacket:
++ length = 0;
++ checksum = 0;
++ srcidx = 1;
++
++ //loop until packet terminator
++ //leave enough room for the checksum at the end
++ while (((c = gdb.textBuffer[srcidx++]) != '#') && (srcidx < kTextBufferSize-2))
++ {
++ if (c == '$')
++ goto startEPacket;
++
++ checksum += c;
++ aBuffer[length++] = c;
++ }
++
++ c = gdb.textBuffer[srcidx++];
++ x = HexCharToValue(c) << 4;
++ c = gdb.textBuffer[srcidx++];
++ x += HexCharToValue (c);
++
++ aBuffer[length++] = 0;
++
++ checksum &= 0xff;
++
++ GDB_Print2("GetPacket %d",length,0);
++ }
++#endif
++#endif
++
++ if(checksum != x)
++ {
++ GDBPutAck('-');
++ length = 0;
++ }
++ else
++ {
++ GDBPutAck('+');
++ }
++ return length;
++}
++
++//Wait for acknowledgement
++//Should we have some way of timing out???
++//return TRUE if ACK
++//return FALSE if NACK
++int GDBGetACK (void)
++{
++ char c;
++ if (gdb.comlink == ne_gdb_serial)
++ {
++ while (1)
++ {
++ c = GDBGetChar ();
++ if (c == '+') return (1);
++ else if (c == '-') return (0);
++ }
++
++ }
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ else
++ {
++ gdb.ACKstatus = ne_gdb_ack_waiting;
++ while (1)
++ {
++ nr_plugs_idle ();
++ if (gdb.ACKstatus == ne_gdb_ack_acked)
++ {
++ gdb.ACKstatus = ne_gdb_ack_notwaiting;
++ return (1);
++ }
++ else if (gdb.ACKstatus == ne_gdb_ack_nacked)
++ {
++ gdb.ACKstatus = ne_gdb_ack_notwaiting;
++ return (0);
++ }
++ }
++ }
++#endif
++#endif
++ return(0);
++}
++
++/*
++ * Send a packet, preceded by $,
++ * and followed by #checksum.
++ */
++void PutGDBPacket(char *aBuffer)
++{
++ int checksum;
++ char c;
++ char *origPtr;
++ int cnt=0;
++
++ origPtr = aBuffer; // Remember in case we get a NACK
++ if (gdb.comlink == ne_gdb_serial)
++ {
++startPutSerial:
++ GDBPutChar('$');
++ checksum = 0;
++ while((c = *aBuffer++) != 0)
++ {
++ checksum += c;
++ GDBPutChar(c);
++ }
++ GDBPutChar('#');
++ GDBPutChar(dHexChars[(checksum >> 4) & 15]);
++ GDBPutChar(dHexChars[checksum & 15]);
++
++ if (!GDBGetACK ())
++ {
++ aBuffer = origPtr;
++ if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
++ }
++ }
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ else
++ {
++ if (gdb.host_ip_address != 0)
++ {
++ int i;
++ int result;
++ char c1;
++
++ i = 0;
++ c = aBuffer[i];
++ if (c==0) return; //there is no data in packet, so why bother sending
++ aBuffer[i++] = '$';
++ checksum = 0;
++ do
++ {
++ checksum += c;
++ c1 = aBuffer[i];
++ aBuffer[i++] = c;
++ c = c1;
++ } while (c != 0);
++
++ aBuffer[i++] = '#';
++ aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
++ aBuffer[i++] = dHexChars[checksum & 15];
++ aBuffer[i++] = 0;
++startPutEth:
++ result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
++ gdb.host_ip_address,
++ gdb.host_port_number);
++
++ if (!GDBGetACK ())
++ {
++ if (++cnt < GDB_RETRY_CNT) goto startPutEth;
++ }
++ aBuffer[0] = 0; //clear packet to
++ }
++ }
++#endif
++#endif
++}
++
++int PutTracePacket(char *aBuffer, int size)
++{
++ int checksum;
++#ifdef ethernet_exists
++ char c;
++#endif
++ int i;
++ int cnt=0;
++
++ if (gdb.comlink == ne_gdb_serial)
++ {
++startPutSerial:
++ GDBPutChar('$');
++ checksum = 0;
++ for (i=0; i<size; i++)
++ {
++ checksum += aBuffer[i];
++ GDBPutChar (aBuffer[i]);
++ }
++ GDBPutChar('#');
++ GDBPutChar(dHexChars[(checksum >> 4) & 15]);
++ GDBPutChar(dHexChars[checksum & 15]);
++
++ if (!GDBGetACK ())
++ {
++ if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
++ }
++ }
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ else
++ {
++ int result;
++ char c1;
++
++ checksum = 0;
++ c = '$';
++ for (i=0; i<size; i++)
++ {
++ checksum += aBuffer[i];
++ c1 = aBuffer[i];
++ aBuffer[i] = c;
++ c = c1;
++ }
++ aBuffer[i++] = c;
++
++ aBuffer[i++] = '#';
++ aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
++ aBuffer[i++] = dHexChars[checksum & 15];
++ aBuffer[i++] = 0;
++ethResend:
++ if (gdb.host_ip_address != 0)
++ {
++ result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
++ gdb.host_ip_address,
++ gdb.host_port_number);
++ }
++ if (!GDBGetACK ())
++ {
++ if (++cnt < GDB_RETRY_CNT) goto ethResend;
++ }
++ aBuffer[0]=0;
++ }
++#endif
++#endif
++ if (cnt < GDB_RETRY_CNT) return 1;
++ else return 0;
++}
++
++void PutGDBOKPacket(char *aBuffer)
++ {
++ aBuffer[0] = 'O';
++ aBuffer[1] = 'K';
++ aBuffer[2] = 0;
++ PutGDBPacket(aBuffer);
++ }
++
++#if nasys_debug_core
++
++//some defines used exclusively for TRACE data xfer
++//stepsize is the ascii hex step value i.e. twice the binary length
++#define stepsize (2*(2*sizeof(int) + sizeof (char)))
++#define MAX_TRACE_BYTES (((int)((2*MAX_DATA_SIZE-2)/stepsize))*stepsize)
++
++int Trace_Read_Intercept (char *aBuffer)
++{
++ int cnt=0;
++ unsigned int data;
++ unsigned char code;
++ int byteCount;
++ unsigned char *w;
++ unsigned short dataAccumulate;
++ int status;
++
++ w = aBuffer;
++ w++; //skip past the m
++ if (*w++ == 't') //see if this is a special "memory trace" packet
++ {
++ w = Hex2Value(w,&byteCount); //get the number of bytes to transfer
++
++ //turn byteCount to a multiple of stepsize
++ byteCount = ((int)(byteCount/stepsize))*stepsize;
++
++ //wait until fifo empties
++ nm_debug_get_reg(status, np_debug_write_status);
++ while (status&np_debug_write_status_writing_mask) nm_debug_get_reg(status,np_debug_write_status);
++
++ // loop through total size
++ while (byteCount > 0)
++ {
++ w=aBuffer; //reset w to beginning of buffer
++
++ //calculate the number of bytes in this packet
++ if (byteCount > MAX_TRACE_BYTES) dataAccumulate = MAX_TRACE_BYTES;
++ else dataAccumulate = byteCount;
++
++ //insert data size at beginning of packet
++ w = MemToHex((char *)&dataAccumulate, w, sizeof (dataAccumulate));
++
++ byteCount -= dataAccumulate; //decrement byteCount
++
++ // accumulate a full buffer
++ for (cnt=0; cnt<dataAccumulate; cnt+=stepsize)
++ {
++ int valid;
++ nm_debug_set_reg (1, np_debug_read_sample); //begin transaction
++
++ //wait until data is ready
++ nm_debug_get_reg (valid, np_debug_data_valid);
++ while (!valid) nm_debug_get_reg(valid,np_debug_data_valid) ;
++
++ nm_debug_get_reg (data, np_debug_trace_address);
++ w = MemToHex ((char *)&data, w, sizeof (int));
++
++ nm_debug_get_reg (data, np_debug_trace_data);
++ w = MemToHex ((char *)&data, w, sizeof (int));
++
++ nm_debug_get_reg (data, np_debug_trace_code);
++ w = MemToHex ((char *)&data, w, sizeof (char));
++ }
++
++ //if one of our data packets doesn't make it, stop sending them
++ //if (PutTracePacket (aBuffer,dataAccumulate+4) != 1) //+4 for size filed
++ // byteCount = 0;
++ /* kenw - My module can't handle the incoming data fast enough. So
++ * send this one packet, and wait for another mt command.
++ */
++ PutTracePacket (aBuffer,dataAccumulate+4);
++ byteCount = 0;
++ }
++ return 1;
++ }
++ return 0;
++}
++
++/*
++#undef stepsize
++#undef MAX_TRACE_BYTES
++*/
++
++#endif
++
++void DoGDBCommand_m(char *aBuffer)
++ {
++ char *w;
++ int startAddr,byteCount;
++
++#if nasys_debug_core
++ /* intercept some access to the dbg peripheral */
++ if (Trace_Read_Intercept (aBuffer)) return;
++#endif
++
++ w = aBuffer;
++ w++; // past 'm'
++ w = Hex2Value(w,&startAddr);
++ w++; // past ','
++ w = Hex2Value(w,&byteCount);
++
++ if (byteCount > MAX_DATA_SIZE) byteCount = MAX_DATA_SIZE;
++
++ // mA,L -- request memory
++ w = aBuffer;
++ w = MemToHex((char *)startAddr,w,byteCount);
++ PutGDBPacket(aBuffer);
++ }
++
++void DoGDBCommand_M(char *aBuffer)
++ {
++ char *w;
++ int startAddr,byteCount;
++
++ w = aBuffer;
++ w++; // past 'M'
++ w = Hex2Value(w,&startAddr);
++ w++; // past ','
++ w = Hex2Value(w,&byteCount);
++ w++; // past ':'
++
++ GDB_Print2("M from %x to %x",startAddr,byteCount);
++
++ // MA,L:values -- write to memory
++
++ w = HexToMem(w,(char *)startAddr,byteCount);
++
++ // Send "OK"
++ PutGDBOKPacket(aBuffer);
++ }
++
++int Debug_Read_Intercept (char *aBuffer)
++{
++ unsigned int data;
++ int index;
++ unsigned char *w;
++
++ w = aBuffer;
++ w++; //skip past the g
++ if (*w++ == 'g') //see if this is a special "register read" packet
++ {
++ w = Hex2Value(w,&index); //get the index of the register to be read
++
++ nm_debug_get_reg (data, index);
++
++ //assemble the output packet
++ w=aBuffer; //reset w to beginning of buffer
++ w = MemToHex((char *)&data, w, sizeof (data));
++ *w++ = 0;
++
++ //now send it
++ PutTracePacket (aBuffer,sizeof (data) * 2);
++
++ return 1;
++ }
++ return 0;
++}
++
++// Return the values of all the registers
++void DoGDBCommand_g(NiosGDBGlobals *g)
++ {
++ char *w;
++
++ if (Debug_Read_Intercept (g->textBuffer)) return;
++
++ w = g->textBuffer;
++
++ w = MemToHex((char *)(&g->registers),w,sizeof(g->registers));
++ PutGDBPacket(g->textBuffer);
++ GDB_Print2("Sent Registers",0,0);
++ }
++
++int Debug_Write_Intercept (char *aBuffer)
++{
++ unsigned int data;
++ int index;
++ unsigned char *w;
++
++ w = aBuffer;
++ w++; //skip past the g
++ if (*w++ == 'g') //see if this is a special "register read" packet
++ {
++ w = Hex2Value(w,&index); //get the index of the register to be written
++ w++; // past ','
++ w = Hex2Value(w,&data);
++
++ nm_debug_set_reg (data, index);
++
++ //now send it
++ // Send "OK"
++ PutGDBOKPacket(aBuffer);
++
++ return 1;
++ }
++ return 0;
++}
++
++void DoGDBCommand_G(NiosGDBGlobals *g)
++ {
++ char *w;
++
++ if (Debug_Write_Intercept (g->textBuffer)) return;
++
++ w = g->textBuffer;
++ w++; // skip past 'G'
++ w = HexToMem(w,(char *)(&g->registers), sizeof(g->registers) );
++
++ // Send "OK"
++ PutGDBOKPacket(g->textBuffer);
++
++ GDB_Print2("Received Registers",0,0);
++ }
++
++// Return last signal value
++void DoGDBCommand_qm(NiosGDBGlobals *g)
++ {
++ char *w;
++
++ w = g->textBuffer;
++
++ *w++ = 'S';
++ *w++ = '2';
++ *w++ = '3'; // make up a signal for now...
++ *w++ = 0;
++ PutGDBPacket(g->textBuffer);
++ }
++
++void DoGDBCommand_q(NiosGDBGlobals *g)
++{
++#ifdef na_ssram_detect_in
++ short int* ssram_exists;
++#endif
++ char *w;
++ w = g->textBuffer;
++
++ w++; /* skip past the q */
++ switch (*w) {
++ case ('A'):
++ w = g->textBuffer;
++
++ /* handle intialization information */
++ /* is nios_ocd available? */
++#ifdef nasys_debug_core
++ *w++ = nasys_debug_core + '0';
++#else
++ *w++ = '0';
++#endif
++ *w++ = ',';
++
++ /* determine if the SSRAM debugger board is
++ * physically present */
++#ifdef na_ssram_detect_in
++ ssram_exists = (short int*) na_ssram_detect_in;
++ *w++ = !(*ssram_exists) + '0';
++#else
++ *w++ = '0';
++#endif
++ *w++ = ',';
++
++ /* print out the max size of a trace packet */
++#if nasys_debug_core
++ sprintf (w, "%04x", MAX_TRACE_BYTES);
++#else
++ sprintf (w, "0000");
++#endif
++
++ break;
++ case ('B'):
++ w = g->textBuffer;
++
++ /* returns 1 if it was an OCD interrupt
++ * returns 0 if it was software breakpoint */
++ if (gdb.trapNumber == nasys_debug_core_irq) {
++ *w++ = '1';
++ } else {
++ *w++ = '0';
++ }
++
++ *w++ = 0;
++ break;
++ default:
++ w = g->textBuffer;
++
++ *w = 0;
++ break;
++ }
++
++ PutGDBPacket(g->textBuffer);
++}
++
++
++void GDBInsertBreakpoint(NiosGDBGlobals *g,short *address)
++ {
++ NiosGDBBreakpoint *b;
++
++ GDB_Print2("breakpoint 0x%x",(int)address,0);
++ if(g->breakpointCount < kMaximumBreakpoints)
++ {
++ b = &g->breakpoint[g->breakpointCount++];
++ b->address = address;
++ b->oldContents = *b->address;
++ *b->address = 0x7904;
++ }
++ }
++
++void GDBRemoveBreakpoints(NiosGDBGlobals *g)
++ {
++ NiosGDBBreakpoint *b;
++ int i;
++
++ for(i = 0; i < g->breakpointCount; i++)
++ {
++ b = &g->breakpoint[i];
++ *b->address = b->oldContents;
++ b->address = 0;
++ }
++
++ g->breakpointCount = 0;
++ }
++
++int NiosInstructionIsTrap5(unsigned short instruction)
++ {
++ return instruction == 0x7905;
++ }
++
++int NiosInstructionIsPrefix(unsigned short instruction)
++ {
++ return (instruction >> 11) == 0x13;
++ }
++
++int NiosInstructionIsSkip(unsigned short instruction)
++ {
++ int op6;
++ int op11;
++
++ op6 = (instruction >> 10);
++ op11 = (instruction >> 5);
++
++ return (op6 == 0x14 // SKP0
++ || op6 == 0x15 // SKP1
++ || op11 == 0x3f6 // SKPRz
++ || op11 == 0x3f7 // SKPS
++ || op11 == 0x3fa); // SKPRnz
++ }
++
++int NiosInstructionIsBranch(unsigned short instruction,short *pc,short **branchTargetOut)
++ {
++ int op4;
++ int op7;
++ int op10;
++ short *branchTarget = 0;
++ int result = 0;
++
++ op4 = (instruction >> 12);
++ op7 = (instruction >> 9);
++ op10 = (instruction >> 6);
++
++ if(op4 == 0x08) // BR, BSR
++ {
++ int offset;
++
++ result = 1;
++ offset = instruction & 0x07ff;
++ if(offset & 0x400) // sign extend
++ offset |= 0xffffF800;
++ branchTarget = pc + offset + 1; // short * gets x2 scaling automatically
++ }
++ else if(op10 == 0x1ff) // JMP, CALL
++ {
++ result = 1;
++ branchTarget = (short *)(gdb.registers.r[instruction & 31] * 2);
++ }
++ else if(op7 == 0x3d) // JMPC, CALLC
++ {
++ result = 1;
++ branchTarget = pc + 1 + (instruction & 0x0ffff);
++#ifdef __nios32__
++ branchTarget = (short *)((int)branchTarget & 0xffffFFFc); // align 32...
++#else
++ branchTarget = (short *)((int)branchTarget & 0xFFFe); // align 16...
++#endif
++ branchTarget = (short *)(*(int *)branchTarget);
++ }
++
++ if(branchTargetOut)
++ *branchTargetOut = branchTarget;
++
++ return result;
++ }
++
++// -------------------------
++// Step at address
++//
++// "stepping" involves inserting a
++// breakpoint at some reasonable
++// spot later than the current program
++// counter
++//
++// On the Nios processor, this is
++// nontrivial. For example, we should
++// not break up a PFX instruction.
++
++void DoGDBCommand_s(NiosGDBGlobals *g)
++ {
++ char *w;
++ int x;
++ short *pc;
++ short *branchTarget;
++ unsigned short instruction;
++ int stepType;
++
++ /*
++ * First, if there's an argument to the packet,
++ * set the new program-counter value
++ */
++
++ w = g->textBuffer;
++ w++;
++ if(HexCharToValue(*w) >= 0)
++ {
++ w = Hex2Value(w,&x);
++ g->registers.pc = x;
++ }
++
++ /*
++ * Scan forward to see what the
++ * most appropriate location(s) for
++ * a breakpoint will be.
++ *
++ * The rules are:
++ * 1. If *pc == PFX, break after modified instruction.
++ * 2. If *pc == BR,BSR,JMP,CALL, break at destination
++ * 3. If *pc == SKIP, break right after SKIP AND after optional instruction,
++ which might, of course, be prefixed.
++ * 4. Anything else, just drop in the breakpoint.
++ */
++
++ pc = (short *)(int)g->registers.pc;
++
++ instruction = *pc;
++ stepType = 0;
++
++ if(NiosInstructionIsPrefix(instruction))
++ {
++ /*
++ * PFX instruction: skip til after it
++ */
++ while(NiosInstructionIsPrefix(instruction))
++ {
++ pc++;
++ instruction = *pc;
++ }
++
++ GDBInsertBreakpoint(g,pc + 1);
++ stepType = 1;
++ }
++ else if(NiosInstructionIsBranch(instruction,pc,&branchTarget))
++ {
++ GDBInsertBreakpoint(g,branchTarget);
++ stepType = 2;
++ }
++ else if(NiosInstructionIsSkip(instruction))
++ {
++ short *pc2;
++ stepType = 3;
++
++ /*
++ * Skip gets to breaks: one after the skippable instruction,
++ * and the skippable instruction itself.
++ *
++ * Since Skips know how to skip over PFX's, we have to, too.
++ */
++ pc2 = pc; // the Skip instruction
++ do
++ {
++ pc2++;
++ } while(NiosInstructionIsPrefix(*pc2));
++ // pc2 now points to first non-PFX after Skip
++ GDBInsertBreakpoint(g,pc2+1);
++ GDBInsertBreakpoint(g,pc+1);
++ }
++ else
++ GDBInsertBreakpoint(g,pc+1); // the genericest case
++
++ GDB_Print2("Program Steppingat 0x%x (%d)",g->registers.pc,stepType);
++ }
++
++// -----------------------------
++// Continue at address
++
++void DoGDBCommand_c(NiosGDBGlobals *g)
++ {
++ char *w;
++ int x;
++ w = g->textBuffer;
++
++ w++; // past command
++
++ // Anything in the packet? if so,
++ // use it to set the PC value
++
++ if(HexCharToValue(*w) >= 0)
++ {
++ w = Hex2Value(w,&x);
++ g->registers.pc = x;
++ }
++
++ GDB_Print2("Program Running at 0x%x",g->registers.pc,0);
++ }
++
++// ----------------------
++// Kill
++
++void DoGDBCommand_k(NiosGDBGlobals *g)
++ {
++ return;
++ }
++
++
++/*
++ * If we've somehow skidded
++ * to a stop just after a PFX instruction
++ * back up the program counter by one.
++ *
++ * That way, we can't end up with an accidentally-unprefixed
++ * instruction.
++ *
++ * We do this just before we begin running
++ * again, so that when the host queries our
++ * registers, we report the place we actually
++ * stopped.
++ */
++
++void MaybeAdjustProgramCounter(NiosGDBGlobals *g)
++ {
++ short instruction;
++ if(g->registers.pc)
++ {
++ instruction = *(short *)(int)(g->registers.pc - 2);
++ if(NiosInstructionIsPrefix(instruction))
++ g->registers.pc -= 2;
++ else
++ {
++ // If the *current* instruction is Trap5, we must skip it!
++ instruction = *(short *)(int)(g->registers.pc);
++ if(NiosInstructionIsTrap5(instruction))
++ g->registers.pc += 2;
++ }
++ }
++ }
++
++/*
++ * GDBMainLoop - this is the main processing loop
++ * for the GDB stub.
++ */
++void GDBMainLoop (void)
++{
++ while(1)
++ {
++ if (GetGDBPacket(gdb.textBuffer) > 0)
++ {
++
++ GDB_Print2(gdb.textBuffer,0,0);
++ switch(gdb.textBuffer[0])
++ {
++ case 's':
++ DoGDBCommand_s(&gdb);
++ goto startRunning;
++ break;
++
++ case 'c': // continue
++ DoGDBCommand_c(&gdb);
++
++ // if the PC is something other than 0, it's
++ // probably ok to exit and go there
++
++ startRunning:
++ if(gdb.registers.pc)
++ {
++ MaybeAdjustProgramCounter(&gdb);
++ return;
++ }
++ break;
++
++ case 'm': // memory read
++ DoGDBCommand_m(gdb.textBuffer);
++ break;
++
++ case 'M': // memory set
++ DoGDBCommand_M(gdb.textBuffer);
++ break;
++
++ case 'g': // registers read
++ DoGDBCommand_g(&gdb);
++ break;
++
++ case 'G': //registers set
++ DoGDBCommand_G(&gdb);
++ break;
++
++ case 'k': //kill process
++ DoGDBCommand_k(&gdb);
++ break;
++
++ case '?': // last exception value
++ DoGDBCommand_qm(&gdb);
++ break;
++
++ case 'q':
++ DoGDBCommand_q(&gdb);
++ break;
++
++ default: // return empty packet, means "yeah yeah".
++ gdb.textBuffer[0] = 0;
++ PutGDBPacket(gdb.textBuffer);
++ break;
++ }
++ }
++ }
++
++}
++
++// ----------main------------
++void GDBMain(void)
++{
++ int i;
++
++ for(i = 0; i < kTextBufferSize; i++)
++ gdb.textBuffer[i] = i;
++
++ GDBRemoveBreakpoints(&gdb);
++
++#ifdef __KERNEL__
++/*
++ * Inform the user that they need to add the symbol file for the application
++ * that is just starting up. Display the .text .data .bss regions.
++ */
++ if (gdb.trapNumber == 5) {
++ extern struct task_struct *_current_task;
++ sprintf(gdb.textBuffer,
++ "\r\n\nGDB: trap 5 at 0x%08lX", gdb.registers.pc);
++ puts(gdb.textBuffer);
++ if (_current_task) {
++ if ( _current_task->mm->start_code > _etext )
++ sprintf(gdb.textBuffer,
++ "\r\nGDB: Enter the following command in the nios-elf-gdb Console Window:"
++ "\r\nGDB: add-symbol-file %s.abself 0x%08lX 0x%08lX 0x%08lX\r\n\n",
++ _current_task->comm,
++ (unsigned long)_current_task->mm->start_code,
++ (unsigned long)_current_task->mm->start_data,
++ (unsigned long)_current_task->mm->end_data );
++ else
++ sprintf(gdb.textBuffer,
++ ", kernel process: %s\r\n", _current_task->comm );
++ } else
++ sprintf(gdb.textBuffer,
++ ", kernel process unknown\r\n" );
++ puts(gdb.textBuffer);
++ }
++#endif
++
++ // Send trapnumber for breakpoint encountered. No other signals.
++
++ gdb.textBuffer[0] = 'S';
++ gdb.textBuffer[1] = '0';
++
++#if nasys_debug_core
++ if (gdb.trapNumber == nasys_debug_core_irq)
++ {
++ /* gdb.textBuffer[2] = '8'; */
++ gdb.textBuffer[2] = '5';
++ }
++ else
++ {
++ gdb.textBuffer[2] = '5';
++ }
++#else
++ gdb.textBuffer[2] = '5';
++#endif
++ gdb.textBuffer[3] = 0;
++ PutGDBPacket(gdb.textBuffer);
++
++ GDB_Print2("Trap %2d At 0x%x",
++ gdb.trapNumber,gdb.registers.pc);
++// printf ("Trap %d at 0x%x\n",gdb.trapNumber,gdb.registers.pc);
++// for (i=0;i<32;i++) printf (" register[%d] = 0x%x\n",i,gdb.registers.r[i]);
++
++ GDBMainLoop ();
++}
++
++// +----------------------------------
++// | gdb_eth_proc -- gets called for udp packets
++// | from the host bound for gdb stub
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++int gdb_eth_proc(int plug_handle,
++ void *context,
++ ns_plugs_packet *p,
++ void *payload,
++ int payload_length)
++{
++ int i;
++ char *buf = (char *)payload;
++ // if this is a stop request, set a flag to stop after nr_plugs_idle
++ // leave it up to the host to prevent stops from being sent while stub is running???
++
++ if (*buf == 3) gdb.stop = 1;
++
++ // if we're waiting for an ack, check that here
++ if (gdb.ACKstatus == ne_gdb_ack_waiting)
++ {
++ if (buf[0] == '+')
++ {
++ gdb.ACKstatus = ne_gdb_ack_acked;
++ return 0;
++ }
++ else if (buf[0] == '-')
++ {
++ gdb.ACKstatus = ne_gdb_ack_nacked;
++ return 0;
++ }
++ }
++ strcpy (gdb.textBuffer, buf); //all commands should be zero terminated strings
++
++ gdb.textBuffer[payload_length] = 0; //terminate string
++
++ gdb.host_ip_address=((ns_plugs_ip_packet *)(p[ne_plugs_ip].header))->source_ip_address;
++ gdb.host_port_number=((ns_plugs_udp_packet *)(p[ne_plugs_udp].header))->source_port;
++
++ return 0;
++}
++
++int nr_dbg_plugs_idle (void)
++{
++ int result;
++
++ result = nr_plugs_idle ();
++ if (gdb.stop)
++ {
++ gdb.stop = 0;
++//;dgt2;tmp; asm ("TRAP #5");
++ }
++ return result;
++}
++#endif
++#endif
++
++
++/*
++ * int main(void)
++ *
++ * All we really do here is install our trap # 3,
++ * and call it once, so that we're living down in
++ * the GDBMain, trap handler.
++ */
++
++extern int StubBreakpointHandler;
++extern int StubHarmlessHandler;
++#if nasys_debug_core
++extern int StubHWBreakpointHandler;
++#endif
++#ifdef nasys_debug_uart
++extern int StubUartHandler;
++#endif
++
++void gdb_local_install(int active)
++{
++ unsigned int *vectorTable;
++ unsigned int stubBreakpointHandler;
++ unsigned int stubHarmlessHandler;
++#if nasys_debug_core
++ unsigned int stubHWBreakpointHandler;
++#endif
++
++ gdb.breakpointCount = 0;
++ gdb.textBuffer[0] = 0;
++
++ vectorTable = (int *)nasys_vector_table;
++ stubBreakpointHandler = ( (unsigned int)(&StubBreakpointHandler) ) >> 1;
++ stubHarmlessHandler = ( (unsigned int)(&StubHarmlessHandler) ) >> 1;
++#if nasys_debug_core
++ stubHWBreakpointHandler = ( (unsigned int)(&StubHWBreakpointHandler) ) >> 1;
++#endif
++
++ /*
++ * Breakpoint & single step both go here
++ */
++ vectorTable[na_BreakpointTrap] = stubBreakpointHandler;
++ vectorTable[na_SingleStepTrap] = stubBreakpointHandler;
++ vectorTable[na_StartGDBTrap] = active ? stubBreakpointHandler : stubHarmlessHandler;
++ /*
++ * If it exists, Hardware Breakpoint has a different entry point
++ */
++#if nasys_debug_core
++ vectorTable[na_debug_peripheral_irq] = stubHWBreakpointHandler;
++#endif
++
++#ifndef __KERNEL__
++#ifdef nasys_debug_uart
++ if (gdb.comlink == ne_gdb_serial)
++ {
++ np_uart *uart = (np_uart *)nasys_debug_uart;
++ unsigned int stubUartHandler = ((unsigned int)(&StubUartHandler)) >> 1;
++
++ vectorTable[nasys_debug_uart_irq] = stubUartHandler; //set Uart int vector
++ uart->np_uartcontrol = np_uartcontrol_irrdy_mask; //enable Rx intr
++ }
++#endif
++#endif
++}
++
++void nios_gdb_install(int active)
++{
++ gdb.comlink = ne_gdb_serial;
++ gdb_local_install (active);
++}
++
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++void nios_gdb_install_ethernet (int active)
++{
++ int result;
++ host_16 host_port = GDB_ETH_PORT;
++
++ gdb.comlink = ne_gdb_ethernet;
++ gdb_local_install (active);
++
++ result = nr_plugs_create (&gdb.gdb_eth_plug, ne_plugs_udp, host_port, gdb_eth_proc, 0, 0);
++ //if unabled to open ethernet plug, switch back to default serial interface
++ if (result)
++ {
++ printf ("nr_plugs_create failed %d\n",result);
++ gdb.comlink = ne_gdb_serial;
++ return;
++ }
++ result = nr_plugs_connect (gdb.gdb_eth_plug, 0, -1, -1);
++ if (result)
++ {
++ printf ("nr_plugs_connect fialed %d\n",result);
++ gdb.comlink = ne_gdb_serial;
++ return;
++ }
++}
++#endif
++#endif
++
++#ifdef nios_gdb_breakpoint
++ #undef nios_gdb_breakpoint
++#endif
++
++void nios_gdb_breakpoint(void)
++ {
++ /*
++ * If you arrived here, you didn't include
++ * the file "nios_peripherals.h", which
++ * defines nios_gdb_breakpoint as a
++ * macro that expands to TRAP 5.
++ *
++ * (No problem, you can step out
++ * of this routine.)
++ */
++//;dgt2;tmp; asm("TRAP 5");
++ }
++
++// end of file
+diff --git a/arch/nios2nommu/kernel/nios_gdb_stub.h b/arch/nios2nommu/kernel/nios_gdb_stub.h
+new file mode 100644
+index 0000000..3900109
+--- /dev/null
++++ b/arch/nios2nommu/kernel/nios_gdb_stub.h
+@@ -0,0 +1,105 @@
++// file: nios_gdb_stub.h
++// Author: Altera Santa Cruz \ 2000
++//
++// You can modify this header file to
++// enable some features useful for
++// debugging the debugger. They're
++// good features also to just show
++// signs of life on your Nios board.
++// But they consume valuable peripherals!
++//
++// The 'GDB_DEBUG_PRINT' option ties
++// up the LCD living on the 5v port,
++// showing useful internals of the stub.
++//
++// dvb@altera.com
++//
++
++#ifdef ETHER_DEBUG
++#ifdef na_enet
++#define ethernet_exists
++#endif
++#endif
++
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++#include "plugs.h"
++#endif
++#endif
++
++#define MAX_DATA_SIZE 650
++#define kTextBufferSize ((2*MAX_DATA_SIZE)+4)
++#define kMaximumBreakpoints 4
++#define GDB_ETH_PORT 7070
++#define GDB_WHOLE_PACKET 0
++#define GDB_SKIP_FIRST 1
++#define GDB_RETRY_CNT 3
++
++/*
++ * This register structure must match
++ * its counterpart in the GDB host, since
++ * it is blasted across in byte notation.
++ */
++typedef struct
++ {
++ int r[32];
++ long pc;
++ short ctl0;
++ short ctl1;
++ short ctl2;
++ short ctl3;
++ } NiosGDBRegisters;
++
++typedef struct
++ {
++ short *address;
++ short oldContents;
++ } NiosGDBBreakpoint;
++
++typedef struct
++ {
++ NiosGDBRegisters registers;
++ int trapNumber; // stashed by ISR, to distinguish types
++ char textBuffer[kTextBufferSize];
++ int breakpointCount; // breakpoints used for stepping
++ int comlink;
++ int stop;
++ int gdb_eth_plug;
++ NiosGDBBreakpoint breakpoint[kMaximumBreakpoints];
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++ volatile int ACKstatus;
++ net_32 host_ip_address;
++ net_16 host_port_number;
++#endif
++#endif
++ } NiosGDBGlobals;
++
++#ifdef ETHER_DEBUG
++#ifdef ethernet_exists
++enum
++{
++ ne_gdb_ack_notwaiting,
++ ne_gdb_ack_waiting,
++ ne_gdb_ack_acked,
++ ne_gdb_ack_nacked
++};
++#endif
++#endif
++
++enum
++{
++ ne_gdb_serial,
++ ne_gdb_ethernet
++};
++
++#ifndef GDB_DEBUG_PRINT
++ #define GDB_DEBUG_PRINT 0
++#endif
++
++void GDB_Main(void); // initialize gdb and begin.
++
++char GDBGetChar(void);
++void GDBPutChar(char c);
++void GDB_Print2(char *s,int v1,int v2);
++
+diff --git a/arch/nios2nommu/kernel/nios_gdb_stub_io.c b/arch/nios2nommu/kernel/nios_gdb_stub_io.c
+new file mode 100644
+index 0000000..e0d8f82
+--- /dev/null
++++ b/arch/nios2nommu/kernel/nios_gdb_stub_io.c
+@@ -0,0 +1,39 @@
++// Modified for uClinux - Vic - Apr 2002
++// From:
++
++// file: nios_gdb_stub_IO.c
++//
++// Single character I/O for Nios GDB Stub
++
++#ifndef __KERNEL__
++#include "nios.h"
++#else
++#include <asm/nios.h>
++#endif
++
++#include "nios_gdb_stub.h"
++
++#ifdef nasys_debug_uart
++ #define GDB_UART nasys_debug_uart
++#endif
++
++char GDBGetChar(void)
++{
++ char c = 0;
++
++#ifdef GDB_UART
++ while( (c = (char)nr_uart_rxchar(GDB_UART)) < 0 )
++ ;
++#endif
++
++ return c;
++}
++
++void GDBPutChar(char c)
++{
++#ifdef GDB_UART
++ nr_uart_txchar(c, GDB_UART);
++#endif
++}
++
++// End of file
+diff --git a/arch/nios2nommu/kernel/nios_gdb_stub_isr.S b/arch/nios2nommu/kernel/nios_gdb_stub_isr.S
+new file mode 100644
+index 0000000..c4af09a
+--- /dev/null
++++ b/arch/nios2nommu/kernel/nios_gdb_stub_isr.S
+@@ -0,0 +1,99 @@
++/*--------------------------------------------------------------------
++ *
++ * Assembly language portions of Nios GDB Stub
++ *
++ * arch\nios2nommu\kernel\switch.S
++ *
++ * Derived from Nios1
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Modified for uClinux - Vic - Apr 2002
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++//;dgt2;tmp;
++
++ .equ ethernet_exists, 1
++
++
++ .equ gdbRegistersGeneral,0
++ .equ gdbRegistersPC,32
++ .equ gdbRegistersCtl0Ctl1,33
++ .equ gdbRegistersCtl2Ctl3,34
++ .equ gdbTrapNumber,35 ; ISR can report trap number here
++
++
++ .text
++
++ .global StubBreakpointHandler
++ .global StubHarmlessHandler
++ .global StubButtonHandler
++ .global StubHWBreakpointHandler
++ .global GDBMain
++
++ .comm _gdb_stub_stack,1024,4 ; Local stack, statically allocated.
++ .equ gdbStubStacktop,_gdb_stub_stack+992
++
++
++StubHarmlessHandler:
++//;dgt2;tmp
++
++ .equ gdbBreakChar,0x3
++ .global StubUartHandler
++
++StubUartHandler:
++//;dgt2;tmp
++
++StubUartRx:
++//;dgt2;tmp
++
++StubHWBreakpointHandler:
++//;dgt2;tmp
++
++StubBreakpointHandler:
++//;dgt2;tmp
++
++#ifdef __KERNEL__
++;----------------------------------------
++; Name: nr_uart_rxchar
++; Description: Read character if available
++; Input: %o0: UART base to use
++; Output: %o0 = character 0-0xff, or -1 if none present
++; Side Effects: %g0 & %g1 altered
++; CWP Depth: 0
++;
++
++ .global nr_uart_rxchar
++nr_uart_rxchar:
++//;dgt2;tmp
++
++
++;----------------------------------------
++; Name: nr_uart_txchar
++; Description: Send a single byte out the UART
++; Input: %o0 = A character
++; %o1 = the UART to use, 0 for default
++; Output: none
++; Side Effects: %g0 & %g1 altered, CPU waits for UART
++; CWP Depth: 0
++;
++
++; nr_uart_txchar
++ .global nr_uart_txchar
++nr_uart_txchar:
++//;dgt2;tmp
++
++#endif
+diff --git a/arch/nios2nommu/kernel/pio.c b/arch/nios2nommu/kernel/pio.c
+new file mode 100644
+index 0000000..013a64b
+--- /dev/null
++++ b/arch/nios2nommu/kernel/pio.c
+@@ -0,0 +1,154 @@
++/*
++ * linux/arch/nios2nommu/kernel/pio.c
++ * "Example" drivers(LEDs and 7 seg displays) of the PIO interface
++ * on Nios Development Kit.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++MODULE_AUTHOR("Microtronix Datacom Ltd.");
++MODULE_DESCRIPTION("Drivers of PIO devices (LEDs and 7 seg) on Nios kit");
++MODULE_LICENSE("GPL");
++
++#undef CONFIG_PIO_SEG
++#ifdef na_seven_seg_pio
++#define CONFIG_PIO_SEG
++#define PIO_SEG_IO na_seven_seg_pio
++#endif
++
++#undef CONFIG_PIO_LED
++#ifdef na_led_pio
++#define CONFIG_PIO_LED
++#define PIO_LED_IO na_led_pio
++#endif
++
++#define PDEBUG printk
++
++/* routines for 7-segment hex display */
++#ifdef CONFIG_PIO_SEG
++static unsigned char _hex_digits_data[] = {
++ 0x01, 0x4f, 0x12, 0x06, 0x4c, /* 0-4 */
++ 0x24, 0x20, 0x0f, 0x00, 0x04, /* 5-9 */
++ 0x08, 0x60, 0x72, 0x42, 0x30, /* a-e */
++ 0x38 /* f */
++};
++
++void pio_seg_write(int value)
++{
++ int led_value;
++
++ /* Left Hand Digit, goes to PIO bits 8-14 */
++ led_value = _hex_digits_data[value & 0xF];
++ led_value |= (_hex_digits_data[(value >> 4) & 0xF]) << 8;
++
++ outl(led_value, &(PIO_SEG_IO->np_piodata));
++}
++
++static void __init pio_seg_init(void)
++{
++ pio_seg_write(0);
++}
++#endif
++
++
++/* routines for LED display */
++#ifdef CONFIG_PIO_LED
++void pio_led_write(int value)
++{
++ np_pio *pio=(np_pio *)(PIO_LED_IO);
++
++ //outl(-1, &pio->np_piodirection);
++ outl(value, &pio->np_piodata);
++}
++
++static void __init pio_led_init(void)
++{
++ np_pio *pio=(np_pio *)(PIO_LED_IO);
++
++ outl(-1, &pio->np_piodirection);
++ outl(0x0, &pio->np_piodata);
++}
++#endif
++
++/* timing routines */
++#if defined(CONFIG_PIO_SEG) || defined(CONFIG_PIO_LED)
++static struct timer_list display_timer;
++static int restart_timer=1;
++static int timer_counter=0;
++static void display_timeout(unsigned long unused)
++{
++#ifdef CONFIG_PIO_SEG
++ pio_seg_write(++timer_counter);
++#endif
++
++#ifdef CONFIG_PIO_LED
++ pio_led_write(timer_counter);
++#endif
++ if (restart_timer) {
++ display_timer.expires = jiffies + HZ; /* one second */
++ add_timer(&display_timer);
++ }
++}
++#endif
++
++int __init pio_init(void)
++{
++#ifdef CONFIG_PIO_SEG
++ request_mem_region((unsigned long)PIO_SEG_IO, sizeof(np_pio), "pio_7seg");
++ pio_seg_init();
++#endif
++
++#ifdef CONFIG_PIO_LED
++ request_mem_region((unsigned long)PIO_LED_IO, sizeof(np_pio), "pio_led");
++ pio_led_init();
++#endif
++
++#if defined(CONFIG_PIO_SEG) || defined(CONFIG_PIO_LED)
++ /* init timer */
++ init_timer(&display_timer);
++ display_timer.function = display_timeout;
++ display_timer.data = 0;
++ display_timer.expires = jiffies + HZ * 10; /* 10 seconds */
++ add_timer(&display_timer);
++#endif
++
++ return 0;
++}
++
++static void __exit pio_exit(void)
++{
++#ifdef CONFIG_PIO_SEG
++ pio_seg_write(0);
++ release_mem_region((unsigned long)PIO_SEG_IO, sizeof(np_pio));
++#endif
++
++#ifdef CONFIG_PIO_LED
++ pio_led_write(0);
++ release_mem_region((unsigned long)PIO_LED_IO, sizeof(np_pio));
++#endif
++
++#if defined(CONFIG_PIO_SEG) || defined(CONFIG_PIO_LED)
++ restart_timer=0;
++ del_timer_sync(&display_timer);
++#endif
++}
++module_init(pio_init);
++module_exit(pio_exit);
++
+diff --git a/arch/nios2nommu/kernel/process.c b/arch/nios2nommu/kernel/process.c
+new file mode 100644
+index 0000000..4cd353c
+--- /dev/null
++++ b/arch/nios2nommu/kernel/process.c
+@@ -0,0 +1,578 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/process.c
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 1995 Hamish Macdonald
++ * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * 68060 fixes by Jesper Skov
++ * Jan/20/2004 dgt NiosII
++ * rdusp() === (pt_regs *) regs->sp
++ * Monday:
++ * asm-nios2nommu\processor.h now bears
++ * inline thread_saved_pc
++ * (struct thread_struct *t)
++ * Friday: it's back here now
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file handles the architecture-dependent parts of process handling..
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/interrupt.h>
++#include <linux/reboot.h>
++#include <linux/uaccess.h>
++#include <linux/fs.h>
++#include <linux/err.h>
++
++#include <asm/system.h>
++#include <asm/traps.h>
++#include <asm/setup.h>
++#include <asm/pgtable.h>
++#include <asm/cacheflush.h>
++
++asmlinkage void ret_from_fork(void);
++
++/*
++ * The following aren't currently used.
++ */
++void (*pm_idle)(void) = NULL;
++EXPORT_SYMBOL(pm_idle);
++
++void (*pm_power_off)(void) = NULL;
++EXPORT_SYMBOL(pm_power_off);
++
++void default_idle(void)
++{
++ local_irq_disable();
++ if (!need_resched()) {
++ local_irq_enable();
++ __asm__("nop"); // was asm sleep
++ } else
++ local_irq_enable();
++}
++
++void (*idle)(void) = default_idle;
++
++/*
++ * The idle thread. There's no useful work to be
++ * done, so just try to conserve power and have a
++ * low exit latency (ie sit in a loop waiting for
++ * somebody to say that they'd like to reschedule)
++ */
++void cpu_idle(void)
++{
++ while (1) {
++ while (!need_resched())
++ idle();
++ preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++ }
++}
++
++/*
++ * The development boards have no way to pull a board
++ * reset. Just jump to the cpu reset address and let
++ * the code in head.S take care of disabling peripherals.
++ */
++
++void machine_restart(char * __unused)
++{
++ local_irq_disable();
++ __asm__ __volatile__ (
++ "jmp %0\n\t"
++ :
++ : "r" (CPU_RESET_ADDRESS)
++ : "r4");
++}
++
++EXPORT_SYMBOL(machine_restart);
++
++void machine_halt(void)
++{
++ local_irq_disable();
++ for (;;);
++}
++
++EXPORT_SYMBOL(machine_halt);
++
++void exit_thread(void)
++{
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++ /* nothing to do ... */
++}
++
++/*
++ * There is no way to power off the development
++ * boards. So just spin lock for now. If you have
++ * your own board with power down circuits add you
++ * specific code here.
++ */
++
++void machine_power_off(void)
++{
++ local_irq_disable();
++ for (;;);
++}
++
++EXPORT_SYMBOL(machine_power_off);
++
++void show_regs(struct pt_regs * regs)
++{
++ printk(KERN_NOTICE "\n");
++
++ printk(KERN_NOTICE "r1: %08lx r2: %08lx r3: %08lx r4: %08lx\n",
++ regs->r1, regs->r2, regs->r3, regs->r4);
++
++ printk(KERN_NOTICE "r5: %08lx r6: %08lx r7: %08lx r8: %08lx\n",
++ regs->r5, regs->r6, regs->r7, regs->r8);
++
++ printk(KERN_NOTICE "r9: %08lx r10: %08lx r11: %08lx r12: %08lx\n",
++ regs->r9, regs->r10, regs->r11, regs->r12);
++
++ printk(KERN_NOTICE "r13: %08lx r14: %08lx r15: %08lx\n",
++ regs->r13, regs->r14, regs->r15);
++
++ printk(KERN_NOTICE "ra: %08lx fp: %08lx sp: %08lx gp: %08lx\n",
++ regs->ra, regs->fp, regs->sp, regs->gp);
++
++ printk(KERN_NOTICE "ea: %08lx estatus: %08lx statusx: %08lx\n",
++ regs->ea, regs->estatus, regs->status_extension);
++}
++
++/*
++ * Create a kernel thread
++ */
++int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
++{
++ long retval;
++ long clone_arg = flags | CLONE_VM;
++ mm_segment_t fs;
++
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ __asm__ __volatile(
++
++ " movi r2, %6\n\t" /* TRAP_ID_SYSCALL */
++ " movi r3, %1\n\t" /* __NR_clone */
++ " mov r4, %5\n\t" /* (clone_arg */
++ /* (flags | CLONE_VM)) */
++ " movia r5, -1\n\t" /* usp: -1 */
++ " trap\n\t" /* sys_clone */
++ "\n\t"
++ " cmpeq r4, r3, zero\n\t"/*2nd return valu in r3 */
++ " bne r4, zero, 1f\n\t"/* 0: parent, just return. */
++ /* See copy_thread, called */
++ /* by do_fork, called by */
++ /* nios2_clone, called by */
++ /* sys_clone, called by */
++ /* syscall trap handler. */
++
++ " mov r4, %4\n\t" /* fn's parameter (arg) */
++ "\n\t"
++ "\n\t"
++ " callr %3\n\t" /* Call function (fn) */
++ "\n\t"
++ " mov r4, r2\n\t" /* fn's rtn code//;dgt2;tmp;*/
++ " movi r2, %6\n\t" /* TRAP_ID_SYSCALL */
++ " movi r3, %2\n\t" /* __NR_exit */
++ " trap\n\t" /* sys_exit() */
++
++ /* Not reached by child. */
++ "1:\n\t"
++ " mov %0, r2\n\t" /* error rtn code (retval) */
++
++ : "=r" (retval) /* %0 */
++
++ : "i" (__NR_clone) /* %1 */
++ , "i" (__NR_exit) /* %2 */
++ , "r" (fn) /* %3 */
++ , "r" (arg) /* %4 */
++ , "r" (clone_arg) /* %5 (flags | CLONE_VM) */
++ , "i" (TRAP_ID_SYSCALL) /* %6 */
++
++ : "r2" /* Clobbered */
++ , "r3" /* Clobbered */
++ , "r4" /* Clobbered */
++ , "r5" /* Clobbered */
++ , "ra" /* Clobbered //;mex1 */
++ );
++
++ set_fs(fs);
++ return retval;
++}
++
++void flush_thread(void)
++{
++ /* Now, this task is no longer a kernel thread. */
++ current->thread.flags &= ~NIOS2_FLAG_KTHREAD;
++
++#ifdef CONFIG_FPU
++ unsigned long zero = 0;
++#endif
++ set_fs(USER_DS);
++#ifdef CONFIG_FPU
++ if (!FPU_IS_EMU)
++...;dgt2;
++ asm volatile (".chip 68k/68881\n\t"
++ "frestore %0@\n\t"
++ ".chip 68k" : : "a" (&zero));
++#endif
++}
++
++/*
++ * "nios2_fork()".. By the time we get here, the
++ * non-volatile registers have also been saved on the
++ * stack. We do some ugly pointer stuff here.. (see
++ * also copy_thread)
++ */
++
++asmlinkage int nios2_fork(struct pt_regs *regs)
++{
++ /* fork almost works, enough to trick you into looking elsewhere :-( */
++ return(-EINVAL);
++}
++
++/*
++ * nios2_execve() executes a new program.
++ */
++asmlinkage int nios2_execve(struct pt_regs *regs)
++{
++ int error;
++ char * filename;
++
++ lock_kernel();
++ filename = getname((char *) regs->r4);
++ error = PTR_ERR(filename);
++ if (IS_ERR(filename))
++ goto out;
++ error = do_execve(filename,
++ (char **) regs->r5,
++ (char **) regs->r6,
++ regs);
++ putname(filename);
++out:
++ unlock_kernel();
++ return error;
++}
++
++asmlinkage int nios2_vfork(struct pt_regs *regs)
++{
++ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL);
++}
++
++asmlinkage int nios2_clone(struct pt_regs *regs)
++{
++ /* r4: clone_flags, r5: child_stack (usp) */
++
++ unsigned long clone_flags;
++ unsigned long newsp;
++
++ clone_flags = regs->r4;
++ newsp = regs->r5;
++ if (!newsp)
++ newsp = regs->sp;
++ return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
++}
++
++int copy_thread(int nr, unsigned long clone_flags,
++ unsigned long usp, unsigned long topstk,
++ struct task_struct * p, struct pt_regs * regs)
++{
++ struct pt_regs * childregs;
++ struct switch_stack * childstack, *stack;
++ unsigned long stack_offset, *retp;
++
++ stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
++ childregs = (struct pt_regs *) ((unsigned long) p->stack + stack_offset);
++ p->thread.kregs = childregs;
++
++ *childregs = *regs;
++ childregs->r2 = 0; //;dgt2;...redundant?...see "rtnvals" below
++
++ retp = ((unsigned long *) regs);
++ stack = ((struct switch_stack *) retp) - 1;
++
++ childstack = ((struct switch_stack *) childregs) - 1;
++ *childstack = *stack;
++ childstack->ra = (unsigned long)ret_from_fork;
++
++ if (usp == -1)
++ p->thread.kregs->sp = (unsigned long) childstack;
++ else
++ p->thread.kregs->sp = usp;
++
++ p->thread.ksp = (unsigned long)childstack;
++
++#ifdef CONFIG_FPU
++ if (!FPU_IS_EMU) {
++ /* Copy the current fpu state */
++...;dgt2;
++ asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
++
++ if (p->thread.fpstate[0])
++ asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
++ "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
++ : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
++ : "memory");
++ /* Restore the state in case the fpu was busy */
++ asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
++ }
++#endif
++
++ /* Set the return value for the child. */
++ childregs->r2 = 0; //;dgt2;...redundant?...see childregs->r2 above
++ childregs->r3 = 1; //;dgt2;...eg: kernel_thread parent test
++
++ /* Set the return value for the parent. */
++ regs->r2 = p->pid; // Return child pid to parent
++ regs->r3 = 0; //;dgt2;...eg: kernel_thread parent test
++
++ return 0;
++}
++
++/* Fill in the fpu structure for a core dump. */
++
++int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
++{
++#ifdef CONFIG_FPU
++ char fpustate[216];
++
++ if (FPU_IS_EMU) {
++ int i;
++
++ memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
++ memcpy(fpu->fpregs, current->thread.fp, 96);
++ /* Convert internal fpu reg representation
++ * into long double format
++ */
++ for (i = 0; i < 24; i += 3)
++ fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
++ ((fpu->fpregs[i] & 0x0000ffff) << 16);
++ return 1;
++ }
++
++ /* First dump the fpu context to avoid protocol violation. */
++...;dgt2;tmp;
++ asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
++ if (!fpustate[0])
++ return 0;
++
++ asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
++ :: "m" (fpu->fpcntl[0])
++ : "memory");
++ asm volatile ("fmovemx %/fp0-%/fp7,%0"
++ :: "m" (fpu->fpregs[0])
++ : "memory");
++#endif
++ return 1;
++}
++
++/*
++ * fill in the user structure for a core dump..
++ */
++void dump_thread(struct pt_regs * regs, struct user * dump)
++{
++ struct switch_stack *sw;
++
++ /* changed the size calculations - should hopefully work better. lbt */
++ dump->magic = CMAGIC;
++ dump->start_code = 0;
++ dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
++ dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
++ dump->u_dsize = ((unsigned long) (current->mm->brk +
++ (PAGE_SIZE-1))) >> PAGE_SHIFT;
++ dump->u_dsize -= dump->u_tsize;
++ dump->u_ssize = 0;
++
++ if (dump->start_stack < TASK_SIZE)
++ dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
++
++ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
++ sw = ((struct switch_stack *)regs) - 1;
++ dump->regs.r1 = regs->r1;
++ dump->regs.r2 = regs->r2;
++ dump->regs.r3 = regs->r3;
++ dump->regs.r4 = regs->r4;
++ dump->regs.r5 = regs->r5;
++ dump->regs.r6 = regs->r6;
++ dump->regs.r7 = regs->r7;
++ dump->regs.r8 = regs->r8;
++ dump->regs.r9 = regs->r9;
++ dump->regs.r10 = regs->r10;
++ dump->regs.r11 = regs->r11;
++ dump->regs.r12 = regs->r12;
++ dump->regs.r13 = regs->r13;
++ dump->regs.r14 = regs->r14;
++ dump->regs.r15 = regs->r15;
++ dump->regs.r16 = sw->r16;
++ dump->regs.r17 = sw->r17;
++ dump->regs.r18 = sw->r18;
++ dump->regs.r19 = sw->r19;
++ dump->regs.r20 = sw->r20;
++ dump->regs.r21 = sw->r21;
++ dump->regs.r22 = sw->r22;
++ dump->regs.r23 = sw->r23;
++ dump->regs.ra = sw->ra;
++ dump->regs.fp = sw->fp;
++ dump->regs.gp = sw->gp;
++ dump->regs.sp = regs->sp;
++ dump->regs.orig_r2 = regs->orig_r2;
++ dump->regs.estatus = regs->estatus;
++ dump->regs.ea = regs->ea;
++ /* dump floating point stuff */
++ // dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
++}
++
++/*
++ * Generic dumping code. Used for panic and debug.
++ */
++void dump(struct pt_regs *fp)
++{
++ unsigned long *sp;
++ unsigned char *tp;
++ int i;
++
++ printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
++ printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
++
++ if (current->mm) {
++ printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
++ (int) current->mm->start_code,
++ (int) current->mm->end_code,
++ (int) current->mm->start_data,
++ (int) current->mm->end_data,
++ (int) current->mm->end_data,
++ (int) current->mm->brk);
++ printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
++ (int) current->mm->start_stack,
++ (int)(((unsigned long) current) + THREAD_SIZE));
++ }
++
++ printk(KERN_EMERG "PC: %08lx\n", fp->ea);
++ printk(KERN_EMERG "SR: %08lx SP: %08lx\n", (long) fp->estatus, (long) fp);
++ printk(KERN_EMERG "r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
++ fp->r4, fp->r5, fp->r6, fp->r7);
++ printk(KERN_EMERG "r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
++ fp->r8, fp->r9, fp->r10, fp->r11);
++ printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) fp->sp,
++ (unsigned int) fp);
++
++ printk(KERN_EMERG "\nCODE:");
++ tp = ((unsigned char *) fp->ea) - 0x20;
++ for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
++ if ((i % 0x10) == 0)
++ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
++ printk(KERN_EMERG "%08x ", (int) *sp++);
++ }
++ printk(KERN_EMERG "\n");
++
++ printk(KERN_EMERG "\nKERNEL STACK:");
++ tp = ((unsigned char *) fp) - 0x40;
++ for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
++ if ((i % 0x10) == 0)
++ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
++ printk(KERN_EMERG "%08x ", (int) *sp++);
++ }
++ printk(KERN_EMERG "\n");
++ printk(KERN_EMERG "\n");
++
++ printk(KERN_EMERG "\nUSER STACK:");
++ tp = (unsigned char *) (fp->sp - 0x10);
++ for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
++ if ((i % 0x10) == 0)
++ printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
++ printk(KERN_EMERG "%08x ", (int) *sp++);
++ }
++ printk(KERN_EMERG "\n\n");
++}
++
++/*
++ * These bracket the sleeping functions..
++ */
++extern void scheduling_functions_start_here(void);
++extern void scheduling_functions_end_here(void);
++#define first_sched ((unsigned long) scheduling_functions_start_here)
++#define last_sched ((unsigned long) scheduling_functions_end_here)
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ unsigned long fp, pc;
++ unsigned long stack_page;
++ int count = 0;
++ if (!p || p == current || p->state == TASK_RUNNING)
++ return 0;
++
++ stack_page = (unsigned long)p;
++ fp = ((struct switch_stack *)p->thread.ksp)->fp; //;dgt2
++ do {
++ if (fp < stack_page+sizeof(struct task_struct) ||
++ fp >= 8184+stack_page) //;dgt2;tmp
++ return 0;
++ pc = ((unsigned long *)fp)[1];
++ if (!in_sched_functions(pc))
++ return pc;
++ fp = *(unsigned long *) fp;
++ } while (count++ < 16); //;dgt2;tmp
++ return 0;
++}
++
++/* Return saved PC of a blocked thread. */
++unsigned long thread_saved_pc(struct task_struct *t)
++{
++ return (t->thread.kregs->ea);
++}
++
++/*
++ * Do necessary setup to start up a newly executed thread.
++ * Will statup in user mode (status_extension = 0).
++ */
++void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
++{
++ memset((void *) regs, 0, sizeof(struct pt_regs));
++ regs->estatus = NIOS2_STATUS_PIE_MSK; // No user mode setting, at least not for now
++ regs->ea = pc;
++ regs->sp = sp;
++
++ /* check if debug flag is set */
++ if (current->thread.flags & NIOS2_FLAG_DEBUG ) {
++ if ( *(u32*)pc == NIOS2_OP_NOP ) {
++ *(u32*)pc = NIOS2_OP_BREAK;
++ flush_icache_range(pc, pc+4);
++ }
++ }
++}
+diff --git a/arch/nios2nommu/kernel/ptrace.c b/arch/nios2nommu/kernel/ptrace.c
+new file mode 100644
+index 0000000..e6ff3b3
+--- /dev/null
++++ b/arch/nios2nommu/kernel/ptrace.c
+@@ -0,0 +1,352 @@
++/*
++ * linux/arch/m68knommu/kernel/ptrace.c
++ *
++ * Copyright (C) 1994 by Hamish Macdonald
++ * Taken from linux/kernel/ptrace.c and modified for M680x0.
++ * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License. See the file COPYING in the main directory of
++ * this archive for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/errno.h>
++#include <linux/ptrace.h>
++#include <linux/user.h>
++
++#include <asm/uaccess.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/processor.h>
++
++/*
++ * does not yet catch signals sent when the child dies.
++ * in exit.c or in signal.c.
++ */
++
++/* determines which bits in the SR the user has access to. */
++/* 1 = access 0 = no access */
++#define SR_MASK 0x00000000
++
++/* Find the stack offset for a register, relative to thread.ksp. */
++#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
++#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
++ - sizeof(struct switch_stack))
++/* Mapping from PT_xxx to the stack offset at which the register is
++ saved. Notice that usp has no stack-slot and needs to be treated
++ specially (see get_reg/put_reg below). */
++static int regoff[] = {
++ -1, PT_REG(r1), PT_REG(r2), PT_REG(r3), PT_REG(r4),
++ PT_REG(r5), PT_REG(r6), PT_REG(r7), PT_REG(r8),
++ PT_REG(r9), PT_REG(r10), PT_REG(r11), PT_REG(r12),
++ PT_REG(r13), PT_REG(r14), PT_REG(r15), SW_REG(r16),
++ SW_REG(r17), SW_REG(r18), SW_REG(r19), SW_REG(r20),
++ SW_REG(r21), SW_REG(r22), SW_REG(r23), -1, -1,
++ PT_REG(gp), PT_REG(sp), -1, -1, PT_REG(ra), -1,
++ PT_REG(estatus), -1, -1, -1
++};
++
++/*
++ * Get contents of register REGNO in task TASK.
++ */
++static inline long get_reg(struct task_struct *task, int regno)
++{
++ unsigned long *addr;
++
++ if (regno == PTR_R0)
++ return 0;
++ else if (regno == PTR_BA)
++ return 0;
++ else if (regno == PTR_STATUS)
++ return 0;
++ else if (regno == PTR_IENABLE)
++ return 0;
++ else if (regno == PTR_IPENDING)
++ return 0;
++ else if (regno < sizeof(regoff)/sizeof(regoff[0]))
++ addr = (unsigned long *)(task->thread.kregs + regoff[regno]);
++ else
++ return 0;
++ return *addr;
++}
++
++/*
++ * Write contents of register REGNO in task TASK.
++ */
++static inline int put_reg(struct task_struct *task, int regno,
++ unsigned long data)
++{
++ unsigned long *addr;
++
++ if (regno == PTR_R0)
++ return -1;
++ else if (regno == PTR_BA)
++ return -1;
++ else if (regno == PTR_STATUS)
++ return -1;
++ else if (regno == PTR_IENABLE)
++ return -1;
++ else if (regno == PTR_IPENDING)
++ return -1;
++ else if (regno < sizeof(regoff)/sizeof(regoff[0]))
++ addr = (unsigned long *) (task->thread.kregs + regoff[regno]);
++ else
++ return -1;
++ *addr = data;
++ return 0;
++}
++
++/*
++ * Called by kernel/ptrace.c when detaching..
++ *
++ * Nothing special to do here, no processor debug support.
++ */
++void ptrace_disable(struct task_struct *child)
++{
++}
++
++long arch_ptrace(struct task_struct *child, long request, long addr, long data)
++{
++ int ret;
++
++ switch (request) {
++ /* when I and D space are separate, these will need to be fixed. */
++ case PTRACE_PEEKTEXT: /* read word at location addr. */
++ case PTRACE_PEEKDATA: {
++ unsigned long tmp;
++ int copied;
++
++ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
++ ret = -EIO;
++ if (copied != sizeof(tmp))
++ break;
++ ret = put_user(tmp,(unsigned long *) data);
++ break;
++ }
++
++ /* read the word at location addr in the USER area. */
++ case PTRACE_PEEKUSR: {
++ unsigned long tmp;
++
++ ret = -EIO;
++ if ((addr & 3) || addr < 0 ||
++ addr > sizeof(struct user) - 3)
++ break;
++
++ tmp = 0; /* Default return condition */
++ addr = addr >> 2; /* temporary hack. */
++ ret = -EIO;
++ if (addr < 19) {
++ tmp = get_reg(child, addr);
++#if 0 // No FPU stuff
++ } else if (addr >= 21 && addr < 49) {
++ tmp = child->thread.fp[addr - 21];
++#ifdef CONFIG_M68KFPU_EMU
++ /* Convert internal fpu reg representation
++ * into long double format
++ */
++ if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
++ tmp = ((tmp & 0xffff0000) << 15) |
++ ((tmp & 0x0000ffff) << 16);
++#endif
++#endif
++ } else if (addr == 49) {
++ tmp = child->mm->start_code;
++ } else if (addr == 50) {
++ tmp = child->mm->start_data;
++ } else if (addr == 51) {
++ tmp = child->mm->end_code;
++ } else
++ break;
++ ret = put_user(tmp,(unsigned long *) data);
++ break;
++ }
++
++ /* when I and D space are separate, this will have to be fixed. */
++ case PTRACE_POKETEXT: /* write the word at location addr. */
++ case PTRACE_POKEDATA:
++ ret = 0;
++ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
++ break;
++ ret = -EIO;
++ break;
++
++ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
++ ret = -EIO;
++ if ((addr & 3) || addr < 0 ||
++ addr > sizeof(struct user) - 3)
++ break;
++
++ addr = addr >> 2; /* temporary hack. */
++
++ if (addr == PTR_ESTATUS) {
++ data &= SR_MASK;
++ data |= get_reg(child, PTR_ESTATUS) & ~(SR_MASK);
++ }
++ if (addr < 19) {
++ if (put_reg(child, addr, data))
++ break;
++ ret = 0;
++ break;
++ }
++#if 0 // No FPU stuff
++ if (addr >= 21 && addr < 48)
++ {
++#ifdef CONFIG_M68KFPU_EMU
++ /* Convert long double format
++ * into internal fpu reg representation
++ */
++ if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
++ data = (unsigned long)data << 15;
++ data = (data & 0xffff0000) |
++ ((data & 0x0000ffff) >> 1);
++ }
++#endif
++ child->thread.fp[addr - 21] = data;
++ ret = 0;
++ }
++#endif
++ break;
++
++ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
++ case PTRACE_CONT: { /* restart after signal. */
++
++ ret = -EIO;
++ if ((unsigned long) data > _NSIG)
++ break;
++ if (request == PTRACE_SYSCALL)
++ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ else
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ child->exit_code = data;
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++ /*
++ * make the child exit. Best I can do is send it a sigkill.
++ * perhaps it should be put in the status that it wants to
++ * exit.
++ */
++ case PTRACE_KILL: {
++
++ ret = 0;
++ if (child->state == EXIT_ZOMBIE) /* already dead */
++ break;
++ child->exit_code = SIGKILL;
++ wake_up_process(child);
++ break;
++ }
++
++ /*
++ * Single stepping requires placing break instructions in
++ * the code to break back. If you are stepping through a
++ * conditional branch you need to decode the test and put
++ * the break in the correct location.
++ */
++ case PTRACE_SINGLESTEP: { /* set the trap flag. */
++
++ ret = -EIO;
++ if ((unsigned long) data > _NSIG)
++ break;
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++
++ child->exit_code = data;
++ /* give it a chance to run. */
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++ case PTRACE_DETACH: /* detach a process that was attached. */
++ ret = ptrace_detach(child, data);
++ break;
++
++ case PTRACE_GETREGS: { /* Get all gp regs from the child. */
++ int i;
++ unsigned long tmp;
++ for (i = 0; i < 19; i++) {
++ tmp = get_reg(child, i);
++ if (put_user(tmp, (unsigned long *) data)) {
++ ret = -EFAULT;
++ break;
++ }
++ data += sizeof(long);
++ }
++ ret = 0;
++ break;
++ }
++
++ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
++ int i;
++ unsigned long tmp;
++ for (i = 0; i < 19; i++) {
++ if (get_user(tmp, (unsigned long *) data)) {
++ ret = -EFAULT;
++ break;
++ }
++ if (i == PTR_ESTATUS) {
++ tmp &= SR_MASK;
++ tmp |= get_reg(child, PTR_ESTATUS) & ~(SR_MASK);
++ }
++ put_reg(child, i, tmp);
++ data += sizeof(long);
++ }
++ ret = 0;
++ break;
++ }
++
++#ifdef PTRACE_GETFPREGS
++ case PTRACE_GETFPREGS: { /* Get the child FPU state. */
++ ret = 0;
++ if (copy_to_user((void *)data, &child->thread.fp,
++ sizeof(struct user_m68kfp_struct)))
++ ret = -EFAULT;
++ break;
++ }
++#endif
++
++#ifdef PTRACE_SETFPREGS
++ case PTRACE_SETFPREGS: { /* Set the child FPU state. */
++ ret = 0;
++ if (copy_from_user(&child->thread.fp, (void *)data,
++ sizeof(struct user_m68kfp_struct)))
++ ret = -EFAULT;
++ break;
++ }
++#endif
++
++ default:
++ ret = -EIO;
++ break;
++ }
++ return ret;
++}
++
++asmlinkage void syscall_trace(void)
++{
++ if (!test_thread_flag(TIF_SYSCALL_TRACE))
++ return;
++ if (!(current->ptrace & PT_PTRACED))
++ return;
++ current->exit_code = SIGTRAP;
++ current->state = TASK_STOPPED;
++ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
++ ? 0x80 : 0));
++ /*
++ * this isn't the same as continuing with a signal, but it will do
++ * for normal use. strace only continues with a signal if the
++ * stopping signal is not SIGTRAP. -brl
++ */
++ if (current->exit_code) {
++ send_sig(current->exit_code, current, 1);
++ current->exit_code = 0;
++ }
++}
+diff --git a/arch/nios2nommu/kernel/semaphore.c b/arch/nios2nommu/kernel/semaphore.c
+new file mode 100644
+index 0000000..0c7d11b
+--- /dev/null
++++ b/arch/nios2nommu/kernel/semaphore.c
+@@ -0,0 +1,155 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/semaphore.c
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++/*
++ * Generic semaphore code. Buyer beware. Do your own
++ * specific changes in <asm/semaphore-helper.h>
++ */
++
++#include <linux/sched.h>
++#include <linux/err.h>
++#include <asm/semaphore-helper.h>
++
++#ifndef CONFIG_RMW_INSNS
++spinlock_t semaphore_wake_lock;
++#endif
++
++/*
++ * Semaphores are implemented using a two-way counter:
++ * The "count" variable is decremented for each process
++ * that tries to sleep, while the "waking" variable is
++ * incremented when the "up()" code goes to wake up waiting
++ * processes.
++ *
++ * Notably, the inline "up()" and "down()" functions can
++ * efficiently test if they need to do any extra work (up
++ * needs to do something only if count was negative before
++ * the increment operation.
++ *
++ * waking_non_zero() (from asm/semaphore.h) must execute
++ * atomically.
++ *
++ * When __up() is called, the count was negative before
++ * incrementing it, and we need to wake up somebody.
++ *
++ * This routine adds one to the count of processes that need to
++ * wake up and exit. ALL waiting processes actually wake up but
++ * only the one that gets to the "waking" field first will gate
++ * through and acquire the semaphore. The others will go back
++ * to sleep.
++ *
++ * Note that these functions are only called when there is
++ * contention on the lock, and as such all this is the
++ * "non-critical" part of the whole semaphore business. The
++ * critical part is the inline stuff in <asm/semaphore.h>
++ * where we want to avoid any extra jumps and calls.
++ */
++asmlinkage void __up(struct semaphore *sem)
++{
++ wake_one_more(sem);
++ wake_up(&sem->wait);
++}
++
++/*
++ * Perform the "down" function. Return zero for semaphore acquired,
++ * return negative for signalled out of the function.
++ *
++ * If called from __down, the return is ignored and the wait loop is
++ * not interruptible. This means that a task waiting on a semaphore
++ * using "down()" cannot be killed until someone does an "up()" on
++ * the semaphore.
++ *
++ * If called from __down_interruptible, the return value gets checked
++ * upon return. If the return value is negative then the task continues
++ * with the negative value in the return register (it can be tested by
++ * the caller).
++ *
++ * Either form may be used in conjunction with "up()".
++ *
++ */
++
++
++#define DOWN_HEAD(task_state) \
++ \
++ \
++ current->state = (task_state); \
++ add_wait_queue(&sem->wait, &wait); \
++ \
++ /* \
++ * Ok, we're set up. sem->count is known to be less than zero \
++ * so we must wait. \
++ * \
++ * We can let go the lock for purposes of waiting. \
++ * We re-acquire it after awaking so as to protect \
++ * all semaphore operations. \
++ * \
++ * If "up()" is called before we call waking_non_zero() then \
++ * we will catch it right away. If it is called later then \
++ * we will have to go through a wakeup cycle to catch it. \
++ * \
++ * Multiple waiters contend for the semaphore lock to see \
++ * who gets to gate through and who has to wait some more. \
++ */ \
++ for (;;) {
++
++#define DOWN_TAIL(task_state) \
++ current->state = (task_state); \
++ } \
++ current->state = TASK_RUNNING; \
++ remove_wait_queue(&sem->wait, &wait);
++
++void __sched __down(struct semaphore * sem)
++{
++ DECLARE_WAITQUEUE(wait, current);
++
++ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
++ if (waking_non_zero(sem))
++ break;
++ schedule();
++ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
++}
++
++int __sched __down_interruptible(struct semaphore * sem)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ int ret = 0;
++
++ DOWN_HEAD(TASK_INTERRUPTIBLE)
++
++ ret = waking_non_zero_interruptible(sem, current);
++ if (ret)
++ {
++ if (ret == 1)
++ /* ret != 0 only if we get interrupted -arca */
++ ret = 0;
++ break;
++ }
++ schedule();
++ DOWN_TAIL(TASK_INTERRUPTIBLE)
++ return ret;
++}
++
++int __down_trylock(struct semaphore * sem)
++{
++ return waking_non_zero_trylock(sem);
++}
+diff --git a/arch/nios2nommu/kernel/setup.c b/arch/nios2nommu/kernel/setup.c
+new file mode 100644
+index 0000000..1f1627b
+--- /dev/null
++++ b/arch/nios2nommu/kernel/setup.c
+@@ -0,0 +1,663 @@
++/*
++ 21Mar2001 1.1 dgt/microtronix: Altera Excalibur/Nios32 port
++ 30Jun2003 kenw/microtronix: Remove cmdline check in flash
++*/
++
++/*
++ * linux/arch/niosnommu/kernel/setup.c
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2001 Vic Phillips {vic@microtronix.com}
++ * Copyleft (C) 2000 James D. Schettine {james@telos-systems.com}
++ * Copyright (C) 1999 Greg Ungerer (gerg@moreton.com.au)
++ * Copyright (C) 1998,2000 D. Jeff Dionne <jeff@lineo.ca>
++ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
++ * Copyright (C) 1995 Hamish Macdonald
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++/*
++ * This file handles the architecture-dependent parts of system setup
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/fs.h>
++#include <linux/fb.h>
++#include <linux/module.h>
++#include <linux/console.h>
++#include <linux/genhd.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/major.h>
++#include <linux/bootmem.h>
++#include <linux/initrd.h>
++#include <linux/seq_file.h>
++
++#include <asm/irq.h>
++#include <asm/byteorder.h>
++#include <asm/asm-offsets.h>
++#include <asm/pgtable.h>
++
++#ifdef CONFIG_BLK_DEV_INITRD
++#include <linux/blk.h>
++#endif
++
++#ifdef CONFIG_NIOS_SPI
++#include <asm/spi.h>
++extern ssize_t spi_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
++extern ssize_t spi_read (struct file *filp, char *buf, size_t count, loff_t *ppos);
++extern loff_t spi_lseek (struct file *filp, loff_t offset, int origin);
++extern int spi_open (struct inode *inode, struct file *filp);
++extern int spi_release (struct inode *inode, struct file *filp);
++#endif
++
++#ifdef CONFIG_CONSOLE
++extern struct consw *conswitchp;
++#endif
++
++unsigned long rom_length;
++unsigned long memory_start;
++unsigned long memory_end;
++
++EXPORT_SYMBOL(memory_start);
++EXPORT_SYMBOL(memory_end);
++
++#ifndef CONFIG_CMDLINE
++#define CONFIG_CMDLINE "CONSOLE=/dev/ttyS0 root=/dev/rom0 ro"
++#endif
++
++#ifndef CONFIG_PASS_CMDLINE
++static char default_command_line[] = CONFIG_CMDLINE;
++#endif
++static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
++
++
++/* r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11*/
++/* r12 r13 r14 r15 or2 ra fp sp gp es ste ea*/
++static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
++ 0, 0, 0, 0, 0, (unsigned long)cpu_idle, 0, 0, 0, 0, 0, 0};
++
++#define CPU "NIOS2"
++
++#if defined (CONFIG_CS89x0) || defined (CONFIG_SMC91111) || defined (CONFIG_OPEN_ETH) || defined (CONFIG_MTIP1000_ETH) || defined (CONFIG_DM9000_ETH) || defined (CONFIG_SMC91X) || defined (CONFIG_DM9000) || defined (CONFIG_DM9KS)
++ #if defined (CONFIG_MTIP1000_ETH) //;dgt3;
++ #include <../drivers/net/mtip1000.h> //;dgt3;
++ #endif //;dgt3;
++
++ unsigned char *excalibur_enet_hwaddr;
++ unsigned char excalibur_enet_hwaddr_array[6];
++#endif
++
++// save args passed from u-boot, called from head.S
++void nios2_boot_init(unsigned r4,unsigned r5,unsigned r6,unsigned r7)
++{
++#if defined(CONFIG_PASS_CMDLINE)
++ if (r4 == 0x534f494e) // r4 is magic NIOS, to become board info check in the future
++ {
++#if defined(CONFIG_BLK_DEV_INITRD)
++ /*
++ * If the init RAM disk has been configured in, and there's a valid
++ * starting address for it, set it up.
++ */
++ if (r5) {
++ initrd_start = r5;
++ initrd_end = r6;
++ }
++#endif /* CONFIG_BLK_DEV_INITRD */
++ if (r7)
++ strncpy(command_line, (char *)r7, COMMAND_LINE_SIZE);
++ }
++#endif
++}
++
++inline void flash_command(int base, int offset, short data)
++{
++ volatile unsigned short * ptr=(unsigned short*) (base);
++
++ ptr[0x555]=0xaa;
++ ptr[0x2aa]=0x55;
++ ptr[offset]=data;
++}
++
++inline void exit_se_flash(int base)
++{
++ flash_command(base, 0x555, 0x90);
++ *(unsigned short*)base=0;
++}
++
++void __init setup_arch(char **cmdline_p)
++{
++ int bootmap_size;
++ extern int _stext, _etext;
++ extern int _edata, _end;
++#ifdef DEBUG
++ extern int _sdata, _sbss, _ebss;
++#ifdef CONFIG_BLK_DEV_BLKMEM
++ extern int *romarray;
++#endif
++#endif
++#if 0 // krh
++ unsigned char *psrc=(unsigned char *)((NIOS_FLASH_START + NIOS_FLASH_END)>>1);
++ int i=0;
++#endif // krh
++
++ memory_start = PAGE_ALIGN((unsigned long)&_end);
++ memory_end = (unsigned long) nasys_program_mem_end;
++
++#if 0 //;kenw;
++ /* copy the command line from booting paramter region */
++ #if defined (nasys_am29lv065d_flash_0) //;dgt;
++ { //;dgt;
++ // ...TBA... //;dgt;
++ } //;dgt;
++ #else //;dgt;
++ flash_command((int)psrc, 0x555, 0x88);
++ while ((*psrc!=0xFF) && (i<sizeof(command_line))) {
++ command_line[i++]=*psrc++;
++ }
++ command_line[i]=0;
++ exit_se_flash(((NIOS_FLASH_START + NIOS_FLASH_END)>>1) );
++ if (command_line[0]==0)
++ #endif //;dgt;
++#endif //;kenw;
++#ifndef CONFIG_PASS_CMDLINE
++ memcpy(command_line, default_command_line, sizeof(default_command_line));
++#endif
++
++ printk("\x0F\r\n\nuClinux/Nios II\n");
++ printk("Altera Nios II support (C) 2004 Microtronix Datacom Ltd.\n");
++
++#ifdef DEBUG
++ printk("KERNEL -> TEXT=0x%08x-0x%08x DATA=0x%08x-0x%08x "
++ "BSS=0x%08x-0x%08x\n", (int) &_stext, (int) &_etext,
++ (int) &_sdata, (int) &_edata,
++ (int) &_sbss, (int) &_ebss);
++ printk("KERNEL -> MEM=0x%06x-0x%06x STACK=0x%06x-0x%06x\n",
++ (int) memory_start, (int) memory_end,
++ (int) memory_end, (int) nasys_program_mem_end);
++#endif
++
++ init_mm.start_code = (unsigned long) &_stext;
++ init_mm.end_code = (unsigned long) &_etext;
++ init_mm.end_data = (unsigned long) &_edata;
++ init_mm.brk = (unsigned long) 0;
++ init_task.thread.kregs = &fake_regs;
++
++#if 0
++ ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
++#endif
++
++ /* Keep a copy of command line */
++ *cmdline_p = &command_line[0];
++
++ memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
++ saved_command_line[COMMAND_LINE_SIZE-1] = 0;
++
++#ifdef DEBUG
++ if (strlen(*cmdline_p))
++ printk("Command line: '%s'\n", *cmdline_p);
++ else
++ printk("No Command line passed\n");
++#endif
++
++
++#if defined (CONFIG_CS89x0) || defined (CONFIG_SMC91111) || defined (CONFIG_OPEN_ETH) || defined (CONFIG_MTIP1000_ETH) || defined (CONFIG_DM9000_ETH) || defined (CONFIG_SMC91X) || defined (CONFIG_DM9000) || defined (CONFIG_DM9KS)
++
++ #if defined (CONFIG_MTIP1000_ETH) //;dgt3;
++ (*((np_mtip_mac *) //;dgt3;
++ (na_mtip_mac_control_port))). //;dgt3;
++ COMMAND_CONFIG = 0; //;dgt3;
++ #endif //;dgt3;
++
++ /* now read the hwaddr of the ethernet --wentao*/
++
++ #if 1 //;dgt2;
++// #if defined (nasys_am29lv065d_flash_0) //;dgt;
++ { //;dgt;
++ unsigned char *flashptr = //;dgt;
++ ((unsigned char *) //;dgt;
++ (( //;dgt;
++ #if defined (na_flash_kernel_end) //;dgt2;
++ na_flash_kernel_end //;dgt2;
++ #else //;dgt2;
++ #if defined (na_flash_kernel_base) //;dgt2;
++ na_flash_kernel_base + //;dgt;
++ #else //;dgt2;
++ na_flash_kernel + //;dgt2;
++ #endif //;dgt2;
++ na_flash_kernel_size //;dgt2;
++ #endif //;dgt2;
++ - 0x00010000))); //;dgt;
++ // last 64K of Altera stratix/cyclone flash //;dgt;
++ //;dgt;
++ if((*((unsigned long *) flashptr)) == 0x00005AFE) //;dgt;
++ { //;dgt;
++ memcpy(excalibur_enet_hwaddr_array, //;dgt;
++ ((void*) (flashptr+4)),6); //;dgt;
++ } //;dgt;
++ else //;dgt;
++ { //;dgt;
++ printk("\nsetup_arch: No persistant network" //;dgt;
++ " settings signature at %08lX\n", //;dgt;
++ ((unsigned long) flashptr)); //;dgt;
++ *((unsigned long *) //;dgt;
++ (&(excalibur_enet_hwaddr_array[0]))) = //;dgt;
++ 0x00ED0700; //;dgt2;
++ /* 0x00-07-ED: Altera Corporation. //;dgt; */
++ *((unsigned short *) //;dgt;
++ (&(excalibur_enet_hwaddr_array[4]))) = //;dgt;
++ 0x0000; //;dgt;
++ /* Should be: 0x-00-07-ED-0A-03-(Random# 0-256) //;dgt2; */
++ /* 0x-00-07-ED-0A-xx-yy Vermont boards //;dgt2; */
++ /* 0x-00-07-ED-0B-xx-yy Rhode Island boards //;dgt2; */
++ /* 0x-00-07-ED-0C-xx-yy Delaware boards //;dgt2; */
++ /* 00 Internal Altera //;dgt2; */
++ /* 01 Beta, pre-production//;dgt2; */
++ /* 02 Beta, pre-production//;dgt2; */
++ /* 03 Customer use //;dgt2; */
++ } //;dgt;
++ } //;dgt;
++ #else //;dgt;
++ flash_command(NIOS_FLASH_START, 0x555, 0x88);
++ memcpy(excalibur_enet_hwaddr_array,(void*)NIOS_FLASH_START,6);
++ exit_se_flash(NIOS_FLASH_START);;
++ #endif //;dgt;
++
++ /* now do the checking, make sure we got a valid addr */
++ if (excalibur_enet_hwaddr_array[0] & (unsigned char)1)
++ {
++ printk("Ethernet hardware address:Clearing invalid bit #0\n");
++ excalibur_enet_hwaddr_array[0] ^= (unsigned char)1;
++ }
++ excalibur_enet_hwaddr=excalibur_enet_hwaddr_array;
++#ifdef DEBUG
++ printk("Setup the hardware addr for ethernet\n\t %02x %02x %02x %02x %02x %02x\n",
++ excalibur_enet_hwaddr[0],excalibur_enet_hwaddr[1],
++ excalibur_enet_hwaddr[2],excalibur_enet_hwaddr[3],
++ excalibur_enet_hwaddr[4],excalibur_enet_hwaddr[5]);
++#endif
++#endif
++
++
++ /*
++ * give all the memory to the bootmap allocator, tell it to put the
++ * boot mem_map at the start of memory
++ */
++ bootmap_size = init_bootmem_node(
++ NODE_DATA(0),
++ memory_start >> PAGE_SHIFT, /* map goes here */
++ PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
++ memory_end >> PAGE_SHIFT);
++ /*
++ * free the usable memory, we have to make sure we do not free
++ * the bootmem bitmap so we then reserve it after freeing it :-)
++ */
++ free_bootmem(memory_start, memory_end - memory_start);
++ reserve_bootmem(memory_start, bootmap_size);
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (initrd_start) reserve_bootmem(virt_to_phys((void *)initrd_start), initrd_end - initrd_start);
++#endif /* CONFIG_BLK_DEV_INITRD */
++ /*
++ * get kmalloc into gear
++ */
++ paging_init();
++#ifdef CONFIG_VT
++#if defined(CONFIG_DUMMY_CONSOLE)
++ conswitchp = &dummy_con;
++#endif
++#endif
++
++#ifdef DEBUG
++ printk("Done setup_arch\n");
++#endif
++
++}
++
++int get_cpuinfo(char * buffer)
++{
++ char *cpu, *mmu, *fpu;
++ u_long clockfreq;
++
++ cpu = CPU;
++ mmu = "none";
++ fpu = "none";
++
++ clockfreq = nasys_clock_freq;
++
++ return(sprintf(buffer, "CPU:\t\t%s\n"
++ "MMU:\t\t%s\n"
++ "FPU:\t\t%s\n"
++ "Clocking:\t%lu.%1luMHz\n"
++ "BogoMips:\t%lu.%02lu\n"
++ "Calibration:\t%lu loops\n",
++ cpu, mmu, fpu,
++ clockfreq/1000000,(clockfreq/100000)%10,
++ (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
++ (loops_per_jiffy*HZ)));
++
++}
++
++/*
++ * Get CPU information for use by the procfs.
++ */
++
++static int show_cpuinfo(struct seq_file *m, void *v)
++{
++ char *cpu, *mmu, *fpu;
++ u_long clockfreq;
++
++ cpu = CPU;
++ mmu = "none";
++ fpu = "none";
++
++ clockfreq = nasys_clock_freq;
++
++ seq_printf(m, "CPU:\t\t%s\n"
++ "MMU:\t\t%s\n"
++ "FPU:\t\t%s\n"
++ "Clocking:\t%lu.%1luMHz\n"
++ "BogoMips:\t%lu.%02lu\n"
++ "Calibration:\t%lu loops\n",
++ cpu, mmu, fpu,
++ clockfreq/1000000,(clockfreq/100000)%10,
++ (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
++ (loops_per_jiffy*HZ));
++
++ return 0;
++}
++
++#ifdef CONFIG_NIOS_SPI
++
++static int bcd2char( int x )
++{
++ if ( (x & 0xF) > 0x90 || (x & 0x0F) > 0x09 )
++ return 99;
++
++ return (((x & 0xF0) >> 4) * 10) + (x & 0x0F);
++}
++
++#endif // CONFIG_NIOS_SPI
++
++
++void arch_gettod(int *year, int *month, int *date, int *hour, int *min, int *sec)
++{
++#ifdef CONFIG_NIOS_SPI
++ /********************************************************************/
++ /* Read the CMOS clock on the Microtronix Datacom O/S Support card. */
++ /* Use the SPI driver code, but circumvent the file system by using */
++ /* its internal functions. */
++ /********************************************************************/
++ int hr;
++
++ struct /*********************************/
++ { /* The SPI payload. Warning: the */
++ unsigned short register_addr; /* sizeof() operator will return */
++ unsigned char value; /* a length of 4 instead of 3! */
++ } spi_data; /*********************************/
++
++
++ if ( spi_open( NULL, NULL ) )
++ {
++ printk( "Cannot open SPI driver to read system CMOS clock.\n" );
++ *year = *month = *date = *hour = *min = *sec = 0;
++ return;
++ }
++
++ spi_lseek( NULL, clockCS, 0 /* == SEEK_SET */ );
++
++ spi_data.register_addr = clock_write_control;
++ spi_data.value = 0x40; // Write protect
++ spi_write( NULL, (const char *)&spi_data, 3, NULL );
++
++ spi_data.register_addr = clock_read_sec;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ *sec = (int)bcd2char( spi_data.value );
++
++ spi_data.register_addr = clock_read_min;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ *min = (int)bcd2char( spi_data.value );
++
++ spi_data.register_addr = clock_read_hour;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ hr = (int)bcd2char( spi_data.value );
++ if ( hr & 0x40 ) // Check 24-hr bit
++ hr = (hr & 0x3F) + 12; // Convert to 24-hr
++
++ *hour = hr;
++
++
++
++ spi_data.register_addr = clock_read_date;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ *date = (int)bcd2char( spi_data.value );
++
++ spi_data.register_addr = clock_read_month;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ *month = (int)bcd2char( spi_data.value );
++
++ spi_data.register_addr = clock_read_year;
++ spi_data.value = 0;
++ spi_read( NULL, (char *)&spi_data, 3, NULL );
++ *year = (int)bcd2char( spi_data.value );
++
++
++ spi_release( NULL, NULL );
++#else
++ *year = *month = *date = *hour = *min = *sec = 0;
++
++#endif
++}
++
++static void *cpuinfo_start (struct seq_file *m, loff_t *pos)
++{
++ return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
++}
++
++static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos)
++{
++ ++*pos;
++ return cpuinfo_start (m, pos);
++}
++
++static void cpuinfo_stop (struct seq_file *m, void *v)
++{
++}
++
++struct seq_operations cpuinfo_op = {
++ start: cpuinfo_start,
++ next: cpuinfo_next,
++ stop: cpuinfo_stop,
++ show: show_cpuinfo
++};
++
++
++// adapted from linux/arch/arm/mach-versatile/core.c and mach-bast
++// note, hardware MAC address is still undefined
++
++#if defined(CONFIG_SMC91X) && defined(na_enet)
++
++#ifndef LAN91C111_REGISTERS_OFFSET
++#define LAN91C111_REGISTERS_OFFSET 0x300
++#endif
++
++static struct resource smc91x_resources[] = {
++ [0] = {
++ .start = na_enet + LAN91C111_REGISTERS_OFFSET,
++ .end = na_enet + LAN91C111_REGISTERS_OFFSET + 0x100 - 1, // 32bits,64k, LAN91C111_REGISTERS_OFFSET 0x0300 ?
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = na_enet_irq,
++ .end = na_enet_irq,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++static struct platform_device smc91x_device = {
++ .name = "smc91x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(smc91x_resources),
++ .resource = smc91x_resources,
++};
++static int __init smc91x_device_init(void)
++{
++ /* customizes platform devices, or adds new ones */
++ platform_device_register(&smc91x_device);
++ return 0;
++}
++arch_initcall(smc91x_device_init);
++#endif // CONFIG_SMC91X
++
++
++#if defined(na_DM9000A) && !defined(na_dm9000) // defs for DE2
++#define na_dm9000 na_DM9000A
++#define na_dm9000_irq na_DM9000A_irq
++#endif
++
++#if defined(CONFIG_DM9000) && defined(na_dm9000)
++#include <linux/dm9000.h>
++static struct resource dm9k_resource[] = {
++ [0] = {
++ .start = na_dm9000,
++ .end = na_dm9000 + 3,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = na_dm9000 + 4,
++ .end = na_dm9000 + 4 + 3,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = na_dm9000_irq,
++ .end = na_dm9000_irq,
++ .flags = IORESOURCE_IRQ,
++ }
++
++};
++static struct dm9000_plat_data dm9k_platdata = {
++ .flags = DM9000_PLATF_16BITONLY,
++};
++static struct platform_device dm9k_device = {
++ .name = "dm9000",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(dm9k_resource),
++ .resource = dm9k_resource,
++ .dev = {
++ .platform_data = &dm9k_platdata,
++ }
++};
++static int __init dm9k_device_init(void)
++{
++ /* customizes platform devices, or adds new ones */
++ platform_device_register(&dm9k_device);
++ return 0;
++}
++arch_initcall(dm9k_device_init);
++#endif // CONFIG_DM9000
++
++
++#if defined(CONFIG_SERIO_ALTPS2) && defined(na_ps2_0)
++
++static struct resource altps2_0_resources[] = {
++ [0] = {
++ .start = na_ps2_0,
++ .end = na_ps2_0 + 0x8 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = na_ps2_0_irq,
++ .end = na_ps2_0_irq,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++static struct platform_device altps2_0_device = {
++ .name = "altps2",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(altps2_0_resources),
++ .resource = altps2_0_resources,
++};
++
++#if defined(na_ps2_1)
++static struct resource altps2_1_resources[] = {
++ [0] = {
++ .start = na_ps2_1,
++ .end = na_ps2_1 + 0x8 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = na_ps2_1_irq,
++ .end = na_ps2_1_irq,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++static struct platform_device altps2_1_device = {
++ .name = "altps2",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(altps2_1_resources),
++ .resource = altps2_1_resources,
++};
++#endif // na_ps2_1
++
++static int __init altps2_device_init(void)
++{
++ /* customizes platform devices, or adds new ones */
++ platform_device_register(&altps2_0_device);
++#if defined(na_ps2_1)
++ platform_device_register(&altps2_1_device);
++#endif // na_ps2_1
++ return 0;
++}
++arch_initcall(altps2_device_init);
++#endif // CONFIG_SERIO_ALTPS2
++
++#if defined(CONFIG_I2C_NIOS2_GPIO) && defined(na_gpio_0)
++#include <asm/gpio.h>
++
++static struct gpio_i2c_pins i2c_gpio_0_pins = {
++ .sda_pin = (na_gpio_0+(0<<2)),
++ .scl_pin = (na_gpio_0+(1<<2)),
++};
++
++static struct platform_device i2c_gpio_0_controller = {
++ .name = "GPIO-I2C",
++ .id = 0,
++ .dev = {
++ .platform_data = &i2c_gpio_0_pins,
++ },
++ .num_resources = 0
++};
++
++static int __init i2c_gpio_device_init(void)
++{
++ /* customizes platform devices, or adds new ones */
++ platform_device_register(&i2c_gpio_0_controller);
++ return 0;
++}
++arch_initcall(i2c_gpio_device_init);
++
++#endif // CONFIG_I2C_NIOS2_GPIO
+diff --git a/arch/nios2nommu/kernel/signal.c b/arch/nios2nommu/kernel/signal.c
+new file mode 100644
+index 0000000..d8c30dc
+--- /dev/null
++++ b/arch/nios2nommu/kernel/signal.c
+@@ -0,0 +1,738 @@
++/*
++ * linux/arch/nios2nommu/kernel/signal.c
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive
++ * for more details.
++ *
++ * Linux/m68k support by Hamish Macdonald
++ *
++ * 68060 fixes by Jesper Skov
++ *
++ * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
++ *
++ * mathemu support by Roman Zippel
++ * (Note: fpstate in the signal context is completely ignored for the emulator
++ * and the internal floating point format is put on stack)
++ *
++ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
++ * Atari :-) Current limitation: Only one sigstack can be active at one time.
++ * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
++ * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
++ * signal handlers!
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ */
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/errno.h>
++#include <linux/wait.h>
++#include <linux/ptrace.h>
++#include <linux/unistd.h>
++#include <linux/stddef.h>
++#include <linux/highuid.h>
++#include <linux/tty.h>
++#include <linux/personality.h>
++#include <linux/binfmts.h>
++
++#include <asm/setup.h>
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/traps.h>
++#include <asm/ucontext.h>
++
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
++
++asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options,
++ struct rusage * ru);
++asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
++
++/*
++ * Atomically swap in the new signal mask, and wait for a signal.
++ */
++asmlinkage int do_sigsuspend(struct pt_regs *regs)
++{
++ old_sigset_t mask = regs->r4; // Verify correct syscall reg
++ sigset_t saveset;
++
++ mask &= _BLOCKABLE;
++ spin_lock_irq(&current->sighand->siglock);
++ saveset = current->blocked;
++ siginitset(&current->blocked, mask);
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ regs->r2 = -EINTR;
++ while (1) {
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ if (do_signal(&saveset, regs))
++ return -EINTR;
++ }
++}
++
++asmlinkage int
++do_rt_sigsuspend(struct pt_regs *regs)
++{
++ sigset_t *unewset = (sigset_t *)regs->r4;
++ size_t sigsetsize = (size_t)regs->r5;
++ sigset_t saveset, newset;
++
++ /* XXX: Don't preclude handling different sized sigset_t's. */
++ if (sigsetsize != sizeof(sigset_t))
++ return -EINVAL;
++
++ if (copy_from_user(&newset, unewset, sizeof(newset)))
++ return -EFAULT;
++ sigdelsetmask(&newset, ~_BLOCKABLE);
++
++ spin_lock_irq(&current->sighand->siglock);
++ saveset = current->blocked;
++ current->blocked = newset;
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ regs->r2 = -EINTR;
++ while (1) {
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ if (do_signal(&saveset, regs))
++ return -EINTR;
++ }
++}
++
++asmlinkage int
++sys_sigaction(int sig, const struct old_sigaction *act,
++ struct old_sigaction *oact)
++{
++ struct k_sigaction new_ka, old_ka;
++ int ret;
++
++ if (act) {
++ old_sigset_t mask;
++ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
++ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
++ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
++ return -EFAULT;
++ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
++ __get_user(mask, &act->sa_mask);
++ siginitset(&new_ka.sa.sa_mask, mask);
++ }
++
++ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
++
++ if (!ret && oact) {
++ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
++ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
++ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
++ return -EFAULT;
++ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
++ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
++ }
++
++ return ret;
++}
++
++/*
++ * Do a signal return; undo the signal stack.
++ *
++ * Keep the return code on the stack quadword aligned!
++ * That makes the cache flush below easier.
++ */
++
++
++struct sigframe
++{
++ char retcode[12];
++ unsigned long extramask[_NSIG_WORDS-1];
++ struct sigcontext sc;
++};
++
++struct rt_sigframe
++{
++ char retcode[12];
++ struct siginfo info;
++ struct ucontext uc;
++};
++
++#ifdef CONFIG_FPU
++
++static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
++
++static inline int restore_fpu_state(struct sigcontext *sc)
++{
++ int err = 1;
++
++ if (FPU_IS_EMU) {
++ /* restore registers */
++ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
++ memcpy(current->thread.fp, sc->sc_fpregs, 24);
++ return 0;
++ }
++
++ if (sc->sc_fpstate[0]) {
++ /* Verify the frame format. */
++ if (sc->sc_fpstate[0] != fpu_version)
++ goto out;
++
++ __asm__ volatile ("Nios II FPU"
++ : /* no outputs */
++ : );
++ }
++ __asm__ volatile ("Nios II FPU"
++ : : );
++ err = 0;
++
++out:
++ return err;
++}
++
++#define FPCONTEXT_SIZE 216
++#define uc_fpstate uc_filler[0]
++#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
++#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
++
++static inline int rt_restore_fpu_state(struct ucontext *uc)
++{
++ unsigned char fpstate[FPCONTEXT_SIZE];
++ int context_size = 0;
++ fpregset_t fpregs;
++ int err = 1;
++
++ if (FPU_IS_EMU) {
++ /* restore fpu control register */
++ if (__copy_from_user(current->thread.fpcntl,
++ &uc->uc_mcontext.fpregs.f_pcr, 12))
++ goto out;
++ /* restore all other fpu register */
++ if (__copy_from_user(current->thread.fp,
++ uc->uc_mcontext.fpregs.f_fpregs, 96))
++ goto out;
++ return 0;
++ }
++
++ if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
++ goto out;
++ if (fpstate[0]) {
++ context_size = fpstate[1];
++
++ /* Verify the frame format. */
++ if (fpstate[0] != fpu_version)
++ goto out;
++ if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
++ sizeof(fpregs)))
++ goto out;
++ __asm__ volatile ("Nios II FPU"
++ : /* no outputs */
++ : );
++ }
++ if (context_size &&
++ __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
++ context_size))
++ goto out;
++ __asm__ volatile ("Nios II FPU"
++ : : );
++ err = 0;
++
++out:
++ return err;
++}
++
++#endif
++
++static inline int
++restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
++ int *pr2)
++{
++ int err = 0;
++ int estatus;
++
++ estatus = regs->estatus;
++
++ /* get previous pt_regs */
++ if (copy_from_user(regs, &usc->regs, sizeof(*regs)))
++ goto badframe;
++
++ /* Prevent user from being able to change
++ * certain processor status bits. Currently nothing.
++ */
++ regs->estatus = (estatus & 0xffffffff) | (regs->estatus & 0);
++
++ *pr2 = regs->r2;
++ regs->orig_r2 = -1; /* disable syscall checks */
++
++#ifdef CONFIG_FPU
++ err |= restore_fpu_state(&context);
++#endif
++
++ return err;
++
++badframe:
++ return 1;
++}
++
++static inline int
++rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
++ struct ucontext *uc, int *pr2)
++{
++ int temp;
++ greg_t *gregs = uc->uc_mcontext.gregs;
++ unsigned long usp;
++ int err;
++
++ err = __get_user(temp, &uc->uc_mcontext.version);
++ if (temp != MCONTEXT_VERSION)
++ goto badframe;
++ /* restore passed registers */
++ err |= __get_user(regs->r1, &gregs[0]);
++ err |= __get_user(regs->r2, &gregs[1]);
++ err |= __get_user(regs->r3, &gregs[2]);
++ err |= __get_user(regs->r4, &gregs[3]);
++ err |= __get_user(regs->r5, &gregs[4]);
++ err |= __get_user(regs->r6, &gregs[5]);
++ err |= __get_user(regs->r7, &gregs[6]);
++ err |= __get_user(regs->r8, &gregs[7]);
++ err |= __get_user(regs->r9, &gregs[8]);
++ err |= __get_user(regs->r10, &gregs[9]);
++ err |= __get_user(regs->r11, &gregs[10]);
++ err |= __get_user(regs->r12, &gregs[11]);
++ err |= __get_user(regs->r13, &gregs[12]);
++ err |= __get_user(regs->r14, &gregs[13]);
++ err |= __get_user(regs->r15, &gregs[14]);
++ err |= __get_user(sw->r16, &gregs[15]);
++ err |= __get_user(sw->r17, &gregs[16]);
++ err |= __get_user(sw->r18, &gregs[17]);
++ err |= __get_user(sw->r19, &gregs[18]);
++ err |= __get_user(sw->r20, &gregs[19]);
++ err |= __get_user(sw->r21, &gregs[20]);
++ err |= __get_user(sw->r22, &gregs[21]);
++ err |= __get_user(sw->r23, &gregs[22]);
++ err |= __get_user(usp, &gregs[23]);
++ err |= __get_user(sw->fp, &gregs[24]); // Verify, should this be settable
++ err |= __get_user(sw->gp, &gregs[25]); // Verify, should this be settable
++
++ err |= __get_user(temp, &gregs[26]); // Not really necessary no user settable bits
++ regs->estatus = (regs->estatus & 0xffffffff) | (temp & 0x0);
++ err |= __get_user(regs->status_extension,
++ &uc->uc_mcontext.status_extension);
++ regs->orig_r2 = -1; /* disable syscall checks */
++
++ if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
++ goto badframe;
++
++ *pr2 = regs->r2;
++ return err;
++
++badframe:
++ return 1;
++}
++
++asmlinkage int do_sigreturn(struct pt_regs *regs)
++{
++ struct sigframe *frame = (struct sigframe *) regs->sp;
++ sigset_t set;
++ int rval;
++
++ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
++ goto badframe;
++ if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
++ (_NSIG_WORDS > 1 &&
++ __copy_from_user(&set.sig[1], &frame->extramask,
++ sizeof(frame->extramask))))
++ goto badframe;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++ spin_lock_irq(&current->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ if (restore_sigcontext(regs, &frame->sc, frame + 1, &rval))
++ goto badframe;
++ return rval;
++
++badframe:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++asmlinkage int do_rt_sigreturn(struct switch_stack *sw)
++{
++ struct pt_regs *regs = (struct pt_regs *) sw + 1;
++ struct rt_sigframe *frame = (struct rt_sigframe *) regs->sp; // Verify, can we follow the stack back
++ sigset_t set;
++ int rval;
++
++ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
++ goto badframe;
++ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
++ goto badframe;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++ spin_lock_irq(&current->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ if (rt_restore_ucontext(regs, sw, &frame->uc, &rval))
++ goto badframe;
++ return rval;
++
++badframe:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++#ifdef CONFIG_FPU
++/*
++ * Set up a signal frame.
++ *
++ * Not converted, no FPU support at moment.
++ */
++
++static inline int save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
++{
++ int err = 0;
++
++ if (FPU_IS_EMU) {
++ /* save registers */
++ err |= copy_to_user(&sc->sc_fpcntl, current->thread.fpcntl, 12);
++ err |= copy_to_user(&sc->sc_fpregs, current->thread.fp, 24);
++ return err;
++ }
++
++ __asm__ volatile ("Nios II FPUt"
++ : : );
++
++ if (sc->sc_fpstate[0]) {
++ fpu_version = sc->sc_fpstate[0];
++ __asm__ volatile ("Nios II FPU"
++ : /* no outputs */
++ :
++ : );
++ }
++ return err;
++}
++
++static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
++{
++ unsigned char fpstate[FPCONTEXT_SIZE];
++ int context_size = 0;
++ int err = 0;
++
++ if (FPU_IS_EMU) {
++ /* save fpu control register */
++ err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
++ current->thread.fpcntl, 12);
++ /* save all other fpu register */
++ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
++ current->thread.fp, 96);
++ return err;
++ }
++
++ __asm__ volatile ("Nios II FPU"
++ : : : );
++
++ err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
++ if (fpstate[0]) {
++ fpregset_t fpregs;
++ context_size = fpstate[1];
++ fpu_version = fpstate[0];
++ __asm__ volatile ("Nios II FPU"
++ : /* no outputs */
++ :
++ : );
++ err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
++ sizeof(fpregs));
++ }
++ if (context_size)
++ err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
++ context_size);
++ return err;
++}
++
++#endif
++
++static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
++ unsigned long mask)
++{
++ int err = 0;
++
++ err |= __put_user(mask, &sc->sc_mask);
++ err |= copy_to_user(&sc->regs, regs, sizeof(*regs));
++#ifdef CONFIG_FPU
++ err |= save_fpu_state(sc, regs);
++#endif
++ return err;
++}
++
++static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
++{
++ struct switch_stack *sw = (struct switch_stack *)regs - 1;
++ greg_t *gregs = uc->uc_mcontext.gregs;
++ int err = 0;
++
++ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
++ err |= __put_user(regs->status_extension,
++ &uc->uc_mcontext.status_extension);
++ err |= __put_user(regs->r1, &gregs[0]);
++ err |= __put_user(regs->r2, &gregs[1]);
++ err |= __put_user(regs->r3, &gregs[2]);
++ err |= __put_user(regs->r4, &gregs[3]);
++ err |= __put_user(regs->r5, &gregs[4]);
++ err |= __put_user(regs->r6, &gregs[5]);
++ err |= __put_user(regs->r7, &gregs[6]);
++ err |= __put_user(regs->r8, &gregs[7]);
++ err |= __put_user(regs->r9, &gregs[8]);
++ err |= __put_user(regs->r10, &gregs[9]);
++ err |= __put_user(regs->r11, &gregs[10]);
++ err |= __put_user(regs->r12, &gregs[11]);
++ err |= __put_user(regs->r13, &gregs[12]);
++ err |= __put_user(regs->r14, &gregs[13]);
++ err |= __put_user(regs->r15, &gregs[14]);
++ err |= __put_user(sw->r16, &gregs[15]);
++ err |= __put_user(sw->r17, &gregs[16]);
++ err |= __put_user(sw->r18, &gregs[17]);
++ err |= __put_user(sw->r19, &gregs[18]);
++ err |= __put_user(sw->r20, &gregs[19]);
++ err |= __put_user(sw->r21, &gregs[20]);
++ err |= __put_user(sw->r22, &gregs[21]);
++ err |= __put_user(sw->r23, &gregs[22]);
++ err |= __put_user(regs->sp, &gregs[23]);
++ err |= __put_user(sw->fp, &gregs[24]);
++ err |= __put_user(sw->gp, &gregs[25]);
++#ifdef CONFIG_FPU
++ err |= rt_save_fpu_state(uc, regs);
++#endif
++ return err;
++}
++
++extern void cache_push_v (unsigned long vaddr, int len);
++
++static inline void push_cache (unsigned long vaddr)
++{
++ cache_push_v(vaddr,12);
++}
++
++static inline void *
++get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
++{
++ unsigned long usp;
++
++ /* Default to using normal stack. */
++ usp = regs->sp;
++
++ /* This is the X/Open sanctioned signal stack switching. */
++ if (ka->sa.sa_flags & SA_ONSTACK) {
++ if (!on_sig_stack(usp))
++ usp = current->sas_ss_sp + current->sas_ss_size;
++ }
++ return (void *)((usp - frame_size) & -8UL); // Verify, is it 32 or 64 bit aligned
++}
++
++static void setup_frame (int sig, struct k_sigaction *ka,
++ sigset_t *set, struct pt_regs *regs)
++{
++ struct sigframe *frame;
++ int err = 0;
++
++ frame = get_sigframe(ka, regs, sizeof(*frame));
++
++ if (_NSIG_WORDS > 1)
++ err |= copy_to_user(frame->extramask, &set->sig[1],
++ sizeof(frame->extramask));
++
++ err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
++
++ /* Set up to return from userspace. */
++ regs->ra = (unsigned long) &frame->retcode[0];
++ /* movi r3,__NR_sigreturn */
++ err |= __put_user(0x00c00004 + (__NR_sigreturn << 6), (long *)(frame->retcode));
++ /* mov r2,r0 */
++ err |= __put_user(0x0005883a, (long *)(frame->retcode + 4));
++ /* trap */
++ err |= __put_user(0x003b683a, (long *)(frame->retcode + 8));
++
++ if (err)
++ goto give_sigsegv;
++
++ push_cache ((unsigned long) &frame->retcode);
++
++ /* Set up registers for signal handler */
++ regs->sp = (unsigned long) frame;
++ regs->r4 = (unsigned long) (current_thread_info()->exec_domain
++ && current_thread_info()->exec_domain->signal_invmap
++ && sig < 32
++ ? current_thread_info()->exec_domain->signal_invmap[sig]
++ : sig);
++ regs->ea = (unsigned long) ka->sa.sa_handler;
++ return;
++
++give_sigsegv:
++ if (sig == SIGSEGV)
++ ka->sa.sa_handler = SIG_DFL;
++ force_sig(SIGSEGV, current);
++}
++
++static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
++ sigset_t *set, struct pt_regs *regs)
++{
++ struct rt_sigframe *frame;
++ int err = 0;
++
++ frame = get_sigframe(ka, regs, sizeof(*frame));
++
++ err |= copy_siginfo_to_user(&frame->info, info);
++
++ /* Create the ucontext. */
++ err |= __put_user(0, &frame->uc.uc_flags);
++ err |= __put_user(0, &frame->uc.uc_link);
++ err |= __put_user((void *)current->sas_ss_sp,
++ &frame->uc.uc_stack.ss_sp);
++ err |= __put_user(sas_ss_flags(regs->sp),
++ &frame->uc.uc_stack.ss_flags);
++ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
++ err |= rt_setup_ucontext(&frame->uc, regs);
++ err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
++
++ /* Set up to return from userspace. */
++ regs->ra = (unsigned long) &frame->retcode[0];
++ /* movi r3,__NR_rt_sigreturn */
++ err |= __put_user(0x00c00004 + (__NR_rt_sigreturn << 6), (long *)(frame->retcode));
++ /* mov r2,r0 */
++ err |= __put_user(0x0005883a, (long *)(frame->retcode + 4));
++ /* trap */
++ err |= __put_user(0x003b683a, (long *)(frame->retcode + 8));
++
++ if (err)
++ goto give_sigsegv;
++
++ push_cache ((unsigned long) &frame->retcode);
++
++ /* Set up registers for signal handler */
++ regs->sp = (unsigned long) frame;
++ regs->r4 = (unsigned long) (current_thread_info()->exec_domain
++ && current_thread_info()->exec_domain->signal_invmap
++ && sig < 32
++ ? current_thread_info()->exec_domain->signal_invmap[sig]
++ : sig);
++ regs->r5 = (unsigned long) &frame->info;
++ regs->r6 = (unsigned long) &frame->uc;
++ regs->ea = (unsigned long) ka->sa.sa_handler;
++ return;
++
++give_sigsegv:
++ if (sig == SIGSEGV)
++ ka->sa.sa_handler = SIG_DFL;
++ force_sig(SIGSEGV, current);
++}
++
++static inline void
++handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
++{
++ switch (regs->r2) {
++ case -ERESTARTNOHAND:
++ if (!has_handler)
++ goto do_restart;
++ regs->r2 = -EINTR;
++ break;
++
++ case -ERESTARTSYS:
++ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
++ regs->r2 = -EINTR;
++ break;
++ }
++ /* fallthrough */
++ case -ERESTARTNOINTR:
++ do_restart:
++ regs->r2 = regs->orig_r2;
++ regs->ea -= 4;
++ break;
++ }
++}
++
++/*
++ * OK, we're invoking a handler
++ */
++static void
++handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
++ sigset_t *oldset, struct pt_regs *regs)
++{
++ /* are we from a system call? */
++ if (regs->orig_r2 >= 0)
++ /* If so, check system call restarting.. */
++ handle_restart(regs, ka, 1);
++
++ /* set up the stack frame */
++ if (ka->sa.sa_flags & SA_SIGINFO)
++ setup_rt_frame(sig, ka, info, oldset, regs);
++ else
++ setup_frame(sig, ka, oldset, regs);
++
++ if (ka->sa.sa_flags & SA_ONESHOT)
++ ka->sa.sa_handler = SIG_DFL;
++
++ if (!(ka->sa.sa_flags & SA_NODEFER)) {
++ spin_lock_irq(&current->sighand->siglock);
++ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
++ sigaddset(&current->blocked,sig);
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++ }
++}
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ */
++asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
++{
++ struct k_sigaction ka;
++ siginfo_t info;
++ int signr;
++
++ /*
++ * We want the common case to go fast, which
++ * is why we may in certain cases get here from
++ * kernel mode. Just return without doing anything
++ * if so.
++ */
++ if (!user_mode(regs))
++ return 1;
++
++ /* FIXME - Do we still need to do this ? */
++ current->thread.kregs = regs;
++
++ if (!oldset)
++ oldset = &current->blocked;
++
++ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++ if (signr > 0) {
++ /* Whee! Actually deliver the signal. */
++ handle_signal(signr, &ka, &info, oldset, regs);
++ return 1;
++ }
++
++ /* Did we come from a system call? */
++ if (regs->orig_r2 >= 0){
++ /* Restart the system call - no handlers present */
++ if (regs->r2 == -ERESTARTNOHAND
++ || regs->r2 == -ERESTARTSYS
++ || regs->r2 == -ERESTARTNOINTR) {
++ regs->r2 = regs->orig_r2;
++ regs->ea -= 4;
++ } else if (regs->r2 == -ERESTART_RESTARTBLOCK) {
++ regs->r2 = __NR_restart_syscall;
++ regs->ea -= 4;
++ }
++ }
++ return 0;
++}
+diff --git a/arch/nios2nommu/kernel/start.c b/arch/nios2nommu/kernel/start.c
+new file mode 100644
+index 0000000..bca81fc
+--- /dev/null
++++ b/arch/nios2nommu/kernel/start.c
+@@ -0,0 +1,502 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/start.c
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ * May/20/2005 dgt Altera NiosII Custom shift instr(s)
++ * possibly assumed by memcpy, etc; ensure
++ * "correct" core loaded therefore if so.
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/system.h>
++#include <asm/nios.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/string.h>
++#include <linux/time.h>
++#include <linux/start_kernel.h>
++
++ #ifdef CONFIG_SERIAL_AJUART //;dgt;20may05;
++ #ifdef CONFIG_SERIAL_AJUART_CONSOLE //;dgt;20may05;
++
++ #include <linux/console.h> //;dgt;20may05;
++ #include <asm/altera_juart.h> //;dgt;20may05;
++
++ extern struct console juart_console; //;dgt;20may05;
++
++ #endif // CONFIG_SERIAL_AJUART //;dgt;20may05;
++ #endif // CONFIG_SERIAL_AJUART_CONSOLE //;dgt;20may05;
++
++//;dgt;20may05; #ifdef CONFIG_CRC_CHECK
++
++// #if defined(CONFIG_NIOS_SERIAL) //;dgt;20may05;
++// #if defined(CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;20may05;
++ #if defined(nasys_printf_uart) //;dgt;20may05;
++ static void putsNoNewLine( unsigned char *s )
++ {
++ while(*s) {
++ while (!(nasys_printf_uart->np_uartstatus &
++ np_uartstatus_trdy_mask));
++ nasys_printf_uart->np_uarttxdata = *s++;
++ }
++ }
++
++ #define NL "\r\n"
++ static void puts(unsigned char *s)
++ {
++ putsNoNewLine( s );
++ putsNoNewLine( NL );
++ }
++ #endif // nasys_printf_uart //;dgt;20may05;
++// #endif // CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;20may05;
++// #endif // CONFIG_NIOS_SERIAL) //;dgt;20may05;
++
++#ifdef CONFIG_CRC_CHECK //;dgt;20may05;
++
++#if 1
++#define outchar(X) { \
++ while (!(nasys_printf_uart->np_uartstatus & np_uartstatus_trdy_mask)); \
++ nasys_printf_uart->np_uarttxdata = (X); }
++#else
++#define outchar(X) putchar(X)
++#endif
++#define outhex(X,Y) { \
++ unsigned long __w; \
++ __w = ((X) >> (Y)) & 0xf; \
++ __w = __w > 0x9 ? 'A' + __w - 0xa : '0' + __w; \
++ outchar(__w); }
++#define outhex8(X) { \
++ outhex(X,4); \
++ outhex(X,0); }
++#define outhex16(X) { \
++ outhex(X,12); \
++ outhex(X,8); \
++ outhex(X,4); \
++ outhex(X,0); }
++#define outhex32(X) { \
++ outhex(X,28); \
++ outhex(X,24); \
++ outhex(X,20); \
++ outhex(X,16); \
++ outhex(X,12); \
++ outhex(X,8); \
++ outhex(X,4); \
++ outhex(X,0); }
++#endif
++
++#if 0
++static unsigned long testvar = 0xdeadbeef;
++#endif
++
++#ifdef CONFIG_CRC_CHECK
++
++
++/******************************************************/
++
++
++extern unsigned long __CRC_Table_Begin;
++
++typedef unsigned char U8;
++typedef unsigned long U32;
++
++/* Table of CRC-32's of all single byte values */
++const U32 crc_32_tab[] = {
++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++ 0x2d02ef8dL
++};
++
++U32 Calc_CRC( const U8 *p, U32 len )
++{
++ U32 crc = (U32)~0L;
++ while (len--)
++ crc = crc_32_tab[0xFF & (crc ^ *p++)] ^ (crc >> 8);
++
++ return crc ^ (U32)~0L;
++}
++
++
++
++/******************************************************/
++
++
++/* hjz: Following time stuff is hacked and modified from uC-libc (various files), which in turn was... */
++/* This is adapted from glibc */
++/* Copyright (C) 1991, 1993 Free Software Foundation, Inc */
++
++#define SECS_PER_HOUR 3600L
++#define SECS_PER_DAY 86400L
++typedef unsigned long time_t;
++
++
++static const unsigned short int __mon_lengths[2][12] = {
++ /* Normal years. */
++ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
++ /* Leap years. */
++ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
++};
++/* This global is exported to the wide world in keeping
++ * with the interface in time.h */
++long int timezone = 0;
++
++static const char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
++static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
++
++/* Nonzero if YEAR is a leap year (every 4 years,
++ except every 100th isn't, and every 400th is). */
++# define __isleap(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
++
++struct tm
++{
++ int tm_sec; /* Seconds. [0-60] (1 leap second) */
++ int tm_min; /* Minutes. [0-59] */
++ int tm_hour; /* Hours. [0-23] */
++ int tm_mday; /* Day. [1-31] */
++ int tm_mon; /* Month. [0-11] */
++ int tm_year; /* Year - 1900. */
++ int tm_wday; /* Day of week. [0-6] */
++ int tm_yday; /* Days in year.[0-365] */
++ int tm_isdst; /* DST. [-1/0/1]*/
++
++# ifdef __USE_BSD
++ long int tm_gmtoff; /* Seconds east of UTC. */
++ __const char *tm_zone; /* Timezone abbreviation. */
++# else
++ long int __tm_gmtoff; /* Seconds east of UTC. */
++ __const char *__tm_zone; /* Timezone abbreviation. */
++# endif
++};
++
++void __tm_conv(struct tm *tmbuf, time_t *t, time_t offset)
++{
++ long days, rem;
++ register int y;
++ register const unsigned short int *ip;
++
++ timezone = -offset;
++
++ 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++;
++ }
++
++ tmbuf->tm_hour = rem / SECS_PER_HOUR;
++ rem %= SECS_PER_HOUR;
++ tmbuf->tm_min = rem / 60;
++ tmbuf->tm_sec = rem % 60;
++
++ /* January 1, 1970 was a Thursday. */
++ tmbuf->tm_wday = (4 + days) % 7;
++ if (tmbuf->tm_wday < 0)
++ tmbuf->tm_wday += 7;
++
++ y = 1970;
++ while (days >= (rem = __isleap(y) ? 366 : 365))
++ {
++ y++;
++ days -= rem;
++ }
++
++ while (days < 0)
++ {
++ y--;
++ days += __isleap(y) ? 366 : 365;
++ }
++
++ tmbuf->tm_year = y - 1900;
++ tmbuf->tm_yday = days;
++
++ ip = __mon_lengths[__isleap(y)];
++ for (y = 0; days >= ip[y]; ++y)
++ days -= ip[y];
++
++ tmbuf->tm_mon = y;
++ tmbuf->tm_mday = days + 1;
++ tmbuf->tm_isdst = -1;
++}
++
++
++
++/* hjz: NOT your traditional ctime: This one includes timezone */
++/* (UTC) and excludes the traditional trailing newline. */
++char *CTime( time_t *t )
++{
++ static char theTime[29];
++ struct tm tm;
++
++ __tm_conv( &tm, t, 0 );
++ sprintf( theTime, "%s %s %02d %02d:%02d:%02d UTC %04d",
++ dayOfWeek[tm.tm_wday], month[tm.tm_mon], tm.tm_mday,
++ tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900 );
++
++ return theTime;
++}
++
++/******************************************************/
++
++
++/* hjz: polled-I/O: Get a char if one is ready, or return -1 */
++int getc( void )
++{
++ if ( nasys_printf_uart->np_uartstatus & np_uartstatus_rrdy_mask )
++ return nasys_printf_uart->np_uartrxdata;
++ else
++ return -1;
++}
++
++
++typedef unsigned long off_t;
++typedef struct
++{
++ U8 *startAddr;
++ U8 *endAddr;
++ U32 CRC;
++ time_t mtime;
++ off_t size; // File size
++ char id[44]; // Filename. If path exceeds available size, name is "..." + last 40 chars of given filename
++ char host[32]; // hostname. If name exceeds available size name is first 28 chars of hostname + "..."
++} FLASH_REGION_DESC;
++
++
++int Test_Flash_Regions(void)
++{
++ FLASH_REGION_DESC *pRegion = (FLASH_REGION_DESC *)&__CRC_Table_Begin;
++ U32 crc;
++ char cBuff[256];
++ int nrFailedRegions = 0;
++ int regionStatus;
++ int i;
++ unsigned int startAddr = (int) pRegion->startAddr;
++ unsigned int endAddr = (int) pRegion->endAddr;
++
++ puts( "***Checking flash CRC's" );
++ if ( (startAddr == -1) || (startAddr >= endAddr)
++ || !( ((startAddr >= (int) NIOS_FLASH_START) && (endAddr < (int) NIOS_FLASH_END))
++ || ((startAddr >= (int) na_flash) && (endAddr < (int) na_flash_end)) ) )
++ {
++ puts( " No Flash regions defined." );
++ return -1;
++ }
++
++
++ for ( i = 0; pRegion->startAddr && pRegion->startAddr != (U8 *)~0L; pRegion++, i++ )
++ {
++ crc = Calc_CRC( pRegion->startAddr, pRegion->endAddr - pRegion->startAddr );
++ if ( crc != pRegion->CRC )
++ {
++ regionStatus = 1;
++ nrFailedRegions++;
++ }
++ else
++ regionStatus = 0;
++
++ sprintf( cBuff, " Region %d: 0x%08lX - 0x%08lX, CRC = 0x%08lX --> %s" NL
++ " From file `%s' on host `%s'" NL
++ " Dated %s, size = %lu bytes",
++ i, (U32)pRegion->startAddr, (U32)pRegion->endAddr, pRegion->CRC,
++ regionStatus ? "***Failed" : "Passed",
++ pRegion->id, pRegion->host, CTime( &pRegion->mtime ), pRegion->size
++ );
++ puts( cBuff );
++ }
++
++ return nrFailedRegions;
++}
++#endif /* CONFIG_CRC_CHECK */
++
++
++int main(void) {
++
++#ifdef DEBUG
++ puts("MAIN: starting c\n");
++#endif
++
++#ifdef CONFIG_KGDB /* builtin GDB stub */
++
++/* Set up GDB stub, and make the first trap into it */
++ nios_gdb_install(1);
++#ifdef CONFIG_BREAK_ON_START
++ puts( "MAIN: trapping to debugger - make sure nios-elf-gdb is running on host." );
++ nios_gdb_breakpoint();
++ nop();
++#endif
++
++#endif /* CONFIG_KGDB */
++
++#ifdef CONFIG_CRC_CHECK
++ #ifdef CONFIG_PROMPT_ON_MISSING_CRC_TABLES
++ if ( Test_Flash_Regions() )
++ #else
++ if ( Test_Flash_Regions() > 0 )
++ #endif
++ {
++ int c;
++ char tmp[3];
++ while ( getc() != -1 ) // flush input
++ ;
++
++ putsNoNewLine( " Do you wish to continue (Y/N) ? " );
++ while ( 1 )
++ {
++ c = getc();
++ if ( c == -1 )
++ continue;
++
++ if ( !isprint( c ) )
++ c = '?';
++
++ sprintf( tmp, "\b%c", c );
++ putsNoNewLine( tmp );
++ c = toupper( c );
++ if ( c == 'Y' )
++ {
++ puts( "" );
++ break;
++ }
++
++ if ( c == 'N' )
++ {
++ puts( NL "***Trapping to monitor..." );
++ return -1;
++ }
++ }
++ }
++ puts( "***Starting kernel..." );
++
++#endif
++
++ // Altera NiosII Custom shift instr(s) possibly //;dgt;
++ // assumed by memcpy, etc; ensure "correct" core //;dgt;
++ // loaded therefore if so. //;dgt;
++
++ #if defined(ALT_CI_ALIGN_32_N) //;dgt;
++ if(ALT_CI_ALIGN_32(1, 0xA9876543, //;dgt;
++ 0xB210FEDC) != 0x10FEDCA9) //;dgt;
++ { //;dgt;
++ goto badshiftci_label; //;dgt;
++ } //;dgt;
++ if(ALT_CI_ALIGN_32(2, 0xA9876543, //;dgt;
++ 0xB210FEDC) != 0xFEDCA987) //;dgt;
++ { //;dgt;
++ goto badshiftci_label; //;dgt;
++ } //;dgt;
++ if(ALT_CI_ALIGN_32(3, 0xA9876543, //;dgt;
++ 0xB210FEDC) != 0xDCA98765) //;dgt;
++ { //;dgt;
++ goto badshiftci_label; //;dgt;
++ } //;dgt;
++ #endif //;dgt;
++ goto gudshiftci_label; //;dgt;
++badshiftci_label: //;dgt;
++ { //;dgt;
++ unsigned char BadCImsg[] = //;dgt;
++ "?...ALT_CI_ALIGNn_321() NOT expected" //;dgt;
++ " NiosII custom instruction\n"; //;dgt;
++ unsigned char CIabortMsg[] = //;dgt;
++ " ...aborting uClinux startup..."; //;dgt;
++
++ #ifdef CONFIG_SERIAL_AJUART //;dgt;
++ #ifdef CONFIG_SERIAL_AJUART_CONSOLE //;dgt;
++ juart_console.index = 0; //;dgt;
++ jtaguart_console_write(&(juart_console), //;dgt;
++ BadCImsg, //;dgt;
++ strlen(BadCImsg)); //;dgt;
++ jtaguart_console_write(&(juart_console), //;dgt;
++ CIabortMsg, //;dgt;
++ strlen(CIabortMsg)); //;dgt;
++ #endif // CONFIG_SERIAL_AJUART //;dgt;
++ #endif // CONFIG_SERIAL_AJUART_CONSOLE //;dgt;
++
++// #if defined(CONFIG_NIOS_SERIAL) //;dgt;
++// #if defined(CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;
++ #if defined(nasys_printf_uart) //;dgt;
++ puts(BadCImsg); //;dgt;
++ puts(CIabortMsg); //;dgt;
++ #endif // nasys_printf_uart //;dgt;
++// #endif // CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;
++// #endif // CONFIG_NIOS_SERIAL) //;dgt;
++
++ panic(" ...wrong fpga core?..."); //;dgt;
++ } //;dgt;
++
++gudshiftci_label: //;dgt;
++
++ start_kernel();
++ return 0;
++}
+diff --git a/arch/nios2nommu/kernel/sys_nios2.c b/arch/nios2nommu/kernel/sys_nios2.c
+new file mode 100644
+index 0000000..8018fb0
+--- /dev/null
++++ b/arch/nios2nommu/kernel/sys_nios2.c
+@@ -0,0 +1,248 @@
++/*
++ * linux/arch/nios2nommu/kernel/sys_nios2.c
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * This file contains various random system calls that
++ * have a non-standard calling sequence on the Linux/nios2nommu
++ * platform.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/errno.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/sem.h>
++#include <linux/msg.h>
++#include <linux/shm.h>
++#include <linux/stat.h>
++#include <linux/syscalls.h>
++#include <linux/mman.h>
++#include <linux/file.h>
++#include <linux/utsname.h>
++#include <linux/fs.h>
++#include <linux/uaccess.h>
++#include <linux/ipc.h>
++#include <linux/unistd.h>
++
++#include <asm/setup.h>
++#include <asm/cachectl.h>
++#include <asm/traps.h>
++#include <asm/ipc.h>
++#include <asm/cacheflush.h>
++
++/*
++ * sys_pipe() is the normal C calling standard for creating
++ * a pipe. It's not the way unix traditionally does this, though.
++ */
++asmlinkage int sys_pipe(unsigned long * fildes)
++{
++ int fd[2];
++ int error;
++
++ error = do_pipe(fd);
++ if (!error) {
++ if (copy_to_user(fildes, fd, 2*sizeof(int)))
++ error = -EFAULT;
++ }
++ return error;
++}
++
++/* common code for old and new mmaps */
++static inline long do_mmap2(
++ unsigned long addr, unsigned long len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff)
++{
++ int error = -EBADF;
++ struct file * file = NULL;
++
++ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
++ if (!(flags & MAP_ANONYMOUS)) {
++ file = fget(fd);
++ if (!file)
++ goto out;
++ }
++
++ down_write(&current->mm->mmap_sem);
++ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
++ up_write(&current->mm->mmap_sem);
++
++ if (file)
++ fput(file);
++out:
++ return error;
++}
++
++asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff)
++{
++ return do_mmap2(addr, len, prot, flags, fd, pgoff);
++}
++
++/*
++ * Perform the select(nd, in, out, ex, tv) and mmap() system
++ * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
++ * handle more than 4 system call parameters, so these system calls
++ * used a memory block for parameter passing..
++ */
++
++struct mmap_arg_struct {
++ unsigned long addr;
++ unsigned long len;
++ unsigned long prot;
++ unsigned long flags;
++ unsigned long fd;
++ unsigned long offset;
++};
++
++asmlinkage int old_mmap(struct mmap_arg_struct *arg)
++{
++ struct mmap_arg_struct a;
++ int error = -EFAULT;
++
++ if (copy_from_user(&a, arg, sizeof(a)))
++ goto out;
++
++ error = -EINVAL;
++ if (a.offset & ~PAGE_MASK)
++ goto out;
++
++ a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
++
++ error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
++out:
++ return error;
++}
++
++struct sel_arg_struct {
++ unsigned long n;
++ fd_set *inp, *outp, *exp;
++ struct timeval *tvp;
++};
++
++asmlinkage int old_select(struct sel_arg_struct *arg)
++{
++ struct sel_arg_struct a;
++
++ if (copy_from_user(&a, arg, sizeof(a)))
++ return -EFAULT;
++ /* sys_select() does the appropriate kernel locking */
++ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
++}
++
++/*
++ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
++ *
++ * This is really horribly ugly.
++ */
++asmlinkage int sys_ipc (uint call, int first, int second,
++ int third, void *ptr, long fifth)
++{
++ int version;
++
++ version = call >> 16; /* hack for backward compatibility */
++ call &= 0xffff;
++
++ if (call <= SEMCTL)
++ switch (call) {
++ case SEMOP:
++ return sys_semop (first, (struct sembuf *)ptr, second);
++ case SEMGET:
++ return sys_semget (first, second, third);
++ case SEMCTL: {
++ union semun fourth;
++ if (!ptr)
++ return -EINVAL;
++ if (get_user(fourth.__pad, (void **) ptr))
++ return -EFAULT;
++ return sys_semctl (first, second, third, fourth);
++ }
++ default:
++ return -EINVAL;
++ }
++ if (call <= MSGCTL)
++ switch (call) {
++ case MSGSND:
++ return sys_msgsnd (first, (struct msgbuf *) ptr,
++ second, third);
++ case MSGRCV:
++ switch (version) {
++ case 0: {
++ struct ipc_kludge tmp;
++ if (!ptr)
++ return -EINVAL;
++ if (copy_from_user (&tmp,
++ (struct ipc_kludge *)ptr,
++ sizeof (tmp)))
++ return -EFAULT;
++ return sys_msgrcv (first, tmp.msgp, second,
++ tmp.msgtyp, third);
++ }
++ default:
++ return sys_msgrcv (first,
++ (struct msgbuf *) ptr,
++ second, fifth, third);
++ }
++ case MSGGET:
++ return sys_msgget ((key_t) first, second);
++ case MSGCTL:
++ return sys_msgctl (first, second,
++ (struct msqid_ds *) ptr);
++ default:
++ return -EINVAL;
++ }
++
++ return -EINVAL;
++}
++
++/* sys_cacheflush -- flush the processor cache. */
++asmlinkage int
++sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
++{
++ flush_cache_all();
++ return(0);
++}
++
++asmlinkage int sys_getpagesize(void)
++{
++ return PAGE_SIZE;
++}
++
++/*
++ * Do a system call from kernel instead of calling sys_execve so we
++ * end up with proper pt_regs.
++ */
++int kernel_execve(const char *filename, char *const argv[], char *const envp[])
++{
++ register long __res __asm__ ("r2") = TRAP_ID_SYSCALL;
++ register long __sc __asm__ ("r3") = __NR_execve;
++ register long __a __asm__ ("r4") = (long) filename;
++ register long __b __asm__ ("r5") = (long) argv;
++ register long __c __asm__ ("r6") = (long) envp;
++ __asm__ __volatile__ ("trap" : "=r" (__res)
++ : "0" (__res), "r" (__sc), "r" (__a), "r" (__b), "r" (__c)
++ : "memory");
++
++ return __res;
++}
+diff --git a/arch/nios2nommu/kernel/syscalltable.S b/arch/nios2nommu/kernel/syscalltable.S
+new file mode 100644
+index 0000000..3507e24
+--- /dev/null
++++ b/arch/nios2nommu/kernel/syscalltable.S
+@@ -0,0 +1,362 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/syscalltable.S
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
++ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
++ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
++ * Kenneth Albanowski <kjahds@kjahds.com>,
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <linux/sys.h>
++#include <linux/linkage.h>
++#include <asm/unistd.h>
++#include <asm/asm-macros.h>
++
++.text
++ALIGN
++ENTRY(sys_call_table)
++ .long sys_ni_syscall /* 0 - old "setup()" system call*/
++ .long sys_exit
++ .long sys_fork
++ .long sys_read
++ .long sys_write
++ .long sys_open /* 5 */
++ .long sys_close
++ .long sys_waitpid
++ .long sys_creat
++ .long sys_link
++ .long sys_unlink /* 10 */
++ .long sys_execve
++ .long sys_chdir
++ .long sys_time
++ .long sys_mknod
++ .long sys_chmod /* 15 */
++ .long sys_chown16
++ .long sys_ni_syscall /* old break syscall holder */
++ .long sys_stat
++ .long sys_lseek
++ .long sys_getpid /* 20 */
++ .long sys_mount
++ .long sys_oldumount
++ .long sys_setuid16
++ .long sys_getuid16
++ .long sys_stime /* 25 */
++ .long sys_ptrace
++ .long sys_alarm
++ .long sys_fstat
++ .long sys_pause
++ .long sys_utime /* 30 */
++ .long sys_ni_syscall /* old stty syscall holder */
++ .long sys_ni_syscall /* old gtty syscall holder */
++ .long sys_access
++ .long sys_nice
++ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
++ .long sys_sync
++ .long sys_kill
++ .long sys_rename
++ .long sys_mkdir
++ .long sys_rmdir /* 40 */
++ .long sys_dup
++ .long sys_pipe
++ .long sys_times
++ .long sys_ni_syscall /* old prof syscall holder */
++ .long sys_brk /* 45 */
++ .long sys_setgid16
++ .long sys_getgid16
++ .long sys_signal
++ .long sys_geteuid16
++ .long sys_getegid16 /* 50 */
++ .long sys_acct
++ .long sys_umount /* recycled never used phys() */
++ .long sys_ni_syscall /* old lock syscall holder */
++ .long sys_ioctl
++ .long sys_fcntl /* 55 */
++ .long sys_ni_syscall /* old mpx syscall holder */
++ .long sys_setpgid
++ .long sys_ni_syscall /* old ulimit syscall holder */
++ .long sys_ni_syscall
++ .long sys_umask /* 60 */
++ .long sys_chroot
++ .long sys_ustat
++ .long sys_dup2
++ .long sys_getppid
++ .long sys_getpgrp /* 65 */
++ .long sys_setsid
++ .long sys_sigaction
++ .long sys_sgetmask
++ .long sys_ssetmask
++ .long sys_setreuid16 /* 70 */
++ .long sys_setregid16
++ .long sys_sigsuspend
++ .long sys_sigpending
++ .long sys_sethostname
++ .long sys_setrlimit /* 75 */
++ .long sys_old_getrlimit
++ .long sys_getrusage
++ .long sys_gettimeofday
++ .long sys_settimeofday
++ .long sys_getgroups16 /* 80 */
++ .long sys_setgroups16
++ .long old_select
++ .long sys_symlink
++ .long sys_lstat
++ .long sys_readlink /* 85 */
++ .long sys_uselib
++ .long sys_ni_syscall /* sys_swapon */
++ .long sys_reboot
++ .long old_readdir
++ .long old_mmap /* 90 */
++ .long sys_munmap
++ .long sys_truncate
++ .long sys_ftruncate
++ .long sys_fchmod
++ .long sys_fchown16 /* 95 */
++ .long sys_getpriority
++ .long sys_setpriority
++ .long sys_ni_syscall /* old profil syscall holder */
++ .long sys_statfs
++ .long sys_fstatfs /* 100 */
++ .long sys_ni_syscall /* was ioperm */
++ .long sys_socketcall
++ .long sys_syslog
++ .long sys_setitimer
++ .long sys_getitimer /* 105 */
++ .long sys_newstat
++ .long sys_newlstat
++ .long sys_newfstat
++ .long sys_ni_syscall
++ .long sys_ni_syscall /* iopl for i386 */ /* 110 */
++ .long sys_vhangup
++ .long sys_ni_syscall /* obsolete idle() syscall */
++ .long sys_ni_syscall /* vm86old for i386 */
++ .long sys_wait4
++ .long sys_ni_syscall /* 115 */ /* sys_swapoff */
++ .long sys_sysinfo
++ .long sys_ipc
++ .long sys_fsync
++ .long sys_sigreturn
++ .long sys_clone /* 120 */
++ .long sys_setdomainname
++ .long sys_newuname
++ .long sys_cacheflush /* modify_ldt for i386 */
++ .long sys_adjtimex
++ .long sys_ni_syscall /* 125 */ /* sys_mprotect */
++ .long sys_sigprocmask
++ .long sys_ni_syscall /* old "creat_module" */
++ .long sys_init_module
++ .long sys_delete_module
++ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
++ .long sys_quotactl
++ .long sys_getpgid
++ .long sys_fchdir
++ .long sys_bdflush
++ .long sys_sysfs /* 135 */
++ .long sys_personality
++ .long sys_ni_syscall /* for afs_syscall */
++ .long sys_setfsuid16
++ .long sys_setfsgid16
++ .long sys_llseek /* 140 */
++ .long sys_getdents
++ .long sys_select
++ .long sys_flock
++ .long sys_ni_syscall /* sys_msync */
++ .long sys_readv /* 145 */
++ .long sys_writev
++ .long sys_getsid
++ .long sys_fdatasync
++ .long sys_sysctl
++ .long sys_ni_syscall /* 150 */ /* sys_mlock */
++ .long sys_ni_syscall /* sys_munlock */
++ .long sys_ni_syscall /* sys_mlockall */
++ .long sys_ni_syscall /* sys_munlockall */
++ .long sys_sched_setparam
++ .long sys_sched_getparam /* 155 */
++ .long sys_sched_setscheduler
++ .long sys_sched_getscheduler
++ .long sys_sched_yield
++ .long sys_sched_get_priority_max
++ .long sys_sched_get_priority_min /* 160 */
++ .long sys_sched_rr_get_interval
++ .long sys_nanosleep
++ .long sys_ni_syscall /* sys_mremap */
++ .long sys_setresuid16
++ .long sys_getresuid16 /* 165 */
++ .long sys_getpagesize /* sys_getpagesize */
++ .long sys_ni_syscall /* old "query_module" */
++ .long sys_poll
++ .long sys_ni_syscall /* sys_nfsservctl */
++ .long sys_setresgid16 /* 170 */
++ .long sys_getresgid16
++ .long sys_prctl
++ .long sys_rt_sigreturn
++ .long sys_rt_sigaction
++ .long sys_rt_sigprocmask /* 175 */
++ .long sys_rt_sigpending
++ .long sys_rt_sigtimedwait
++ .long sys_rt_sigqueueinfo
++ .long sys_rt_sigsuspend
++ .long sys_pread64 /* 180 */
++ .long sys_pwrite64
++ .long sys_lchown16
++ .long sys_getcwd
++ .long sys_capget
++ .long sys_capset /* 185 */
++ .long sys_sigaltstack
++ .long sys_sendfile
++ .long sys_ni_syscall /* streams1 */
++ .long sys_ni_syscall /* streams2 */
++ .long sys_vfork /* 190 */
++ .long sys_getrlimit
++ .long sys_mmap2
++ .long sys_truncate64
++ .long sys_ftruncate64
++ .long sys_stat64 /* 195 */
++ .long sys_lstat64
++ .long sys_fstat64
++ .long sys_chown
++ .long sys_getuid
++ .long sys_getgid /* 200 */
++ .long sys_geteuid
++ .long sys_getegid
++ .long sys_setreuid
++ .long sys_setregid
++ .long sys_getgroups /* 205 */
++ .long sys_setgroups
++ .long sys_fchown
++ .long sys_setresuid
++ .long sys_getresuid
++ .long sys_setresgid /* 210 */
++ .long sys_getresgid
++ .long sys_lchown
++ .long sys_setuid
++ .long sys_setgid
++ .long sys_setfsuid /* 215 */
++ .long sys_setfsgid
++ .long sys_pivot_root
++ .long sys_ni_syscall
++ .long sys_ni_syscall
++ .long sys_getdents64 /* 220 */
++ .long sys_gettid
++ .long sys_tkill
++ .long sys_setxattr
++ .long sys_lsetxattr
++ .long sys_fsetxattr /* 225 */
++ .long sys_getxattr
++ .long sys_lgetxattr
++ .long sys_fgetxattr
++ .long sys_listxattr
++ .long sys_llistxattr /* 230 */
++ .long sys_flistxattr
++ .long sys_removexattr
++ .long sys_lremovexattr
++ .long sys_fremovexattr
++ .long sys_futex /* 235 */
++ .long sys_sendfile64
++ .long sys_ni_syscall /* sys_mincore */
++ .long sys_ni_syscall /* sys_madvise */
++ .long sys_fcntl64
++ .long sys_readahead /* 240 */
++ .long sys_io_setup
++ .long sys_io_destroy
++ .long sys_io_getevents
++ .long sys_io_submit
++ .long sys_io_cancel /* 245 */
++ .long sys_fadvise64
++ .long sys_exit_group
++ .long sys_lookup_dcookie
++ .long sys_epoll_create
++ .long sys_epoll_ctl /* 250 */
++ .long sys_epoll_wait
++ .long sys_ni_syscall /* sys_remap_file_pages */
++ .long sys_set_tid_address
++ .long sys_timer_create
++ .long sys_timer_settime /* 255 */
++ .long sys_timer_gettime
++ .long sys_timer_getoverrun
++ .long sys_timer_delete
++ .long sys_clock_settime
++ .long sys_clock_gettime /* 260 */
++ .long sys_clock_getres
++ .long sys_clock_nanosleep
++ .long sys_statfs64
++ .long sys_fstatfs64
++ .long sys_tgkill /* 265 */
++ .long sys_utimes
++ .long sys_fadvise64_64
++ .long sys_mbind
++ .long sys_get_mempolicy
++ .long sys_set_mempolicy /* 270 */
++ .long sys_mq_open
++ .long sys_mq_unlink
++ .long sys_mq_timedsend
++ .long sys_mq_timedreceive
++ .long sys_mq_notify /* 275 */
++ .long sys_mq_getsetattr
++ .long sys_waitid
++ .long sys_ni_syscall /* sys_setaltroot */
++ .long sys_ni_syscall /* sys_add_key */
++ .long sys_ni_syscall /* 280 */ /* sys_request_key */
++ .long sys_ni_syscall /* sys_keyctl */
++ .long sys_ioprio_set
++ .long sys_ioprio_get
++ .long sys_inotify_init
++ .long sys_inotify_add_watch /* 285 */
++ .long sys_inotify_rm_watch
++ .long sys_migrate_pages
++ .long sys_openat
++ .long sys_mkdirat
++ .long sys_mknodat /* 290 */
++ .long sys_fchownat
++ .long sys_futimesat
++ .long sys_fstatat64
++ .long sys_unlinkat
++ .long sys_renameat /* 295 */
++ .long sys_linkat
++ .long sys_symlinkat
++ .long sys_readlinkat
++ .long sys_fchmodat
++ .long sys_faccessat /* 300 */
++ .long sys_ni_syscall /* Reserved for pselect6 */
++ .long sys_ni_syscall /* Reserved for ppoll */
++ .long sys_unshare
++ .long sys_set_robust_list
++ .long sys_get_robust_list /* 305 */
++ .long sys_splice
++ .long sys_sync_file_range
++ .long sys_tee
++ .long sys_vmsplice
++ .long sys_move_pages /* 310 */
++ .long sys_sched_setaffinity
++ .long sys_sched_getaffinity
++ .long sys_kexec_load
++ .long sys_getcpu
++ .long sys_epoll_pwait /* 315 */
++ .long sys_utimensat
++ .long sys_signalfd
++ .long sys_timerfd
++ .long sys_eventfd
++ .long sys_pread64
++ .long sys_pwrite64 /* 321 */
++
++ .rept NR_syscalls - 322
++ .long sys_ni_syscall
++ .endr
++
+diff --git a/arch/nios2nommu/kernel/time.c b/arch/nios2nommu/kernel/time.c
+new file mode 100644
+index 0000000..3b536fe
+--- /dev/null
++++ b/arch/nios2nommu/kernel/time.c
+@@ -0,0 +1,219 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/kernel/time.c
++ *
++ * Architecture specific time handling details.
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Most of the stuff is located in the machine specific files.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ * Copyright (C) 1998-2000 D. Jeff Dionne <jeff@lineo.ca>,
++ * Kenneth Albanowski <kjahds@kjahds.com>,
++ * Copyright (C) 1991, 1992, 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 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++#include <linux/profile.h>
++#include <linux/module.h>
++#include <linux/irq.h>
++
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/nios.h>
++
++#define TICK_SIZE (tick_nsec / 1000)
++
++unsigned long cpu_khz;
++static inline int set_rtc_mmss(unsigned long nowtime)
++{
++ return 0;
++}
++
++/* Timer timeout status */
++#define nios2_timer_TO (inw(&na_timer0->np_timerstatus) & np_timerstatus_to_mask)
++
++/* Timer snapshot */
++static inline unsigned long nios2_read_timercount(void)
++{
++ unsigned long count;
++
++ outw(0, &na_timer0->np_timersnapl);
++ count = inw(&na_timer0->np_timersnaph) << 16 | inw(&na_timer0->np_timersnapl);
++
++ return count;
++}
++
++/*
++ * Should return useconds since last timer tick
++ */
++static unsigned long gettimeoffset(void)
++{
++ unsigned long offset;
++ unsigned long count;
++
++ count = nios2_read_timercount();
++ offset = ((nasys_clock_freq/HZ)-1 - nios2_read_timercount()) \
++ / (nasys_clock_freq / USEC_PER_SEC);
++
++ /* Check if we just wrapped the counters and maybe missed a tick */
++ if (nios2_timer_TO && (offset < (100000 / HZ / 2)))
++ offset += (USEC_PER_SEC / HZ);
++
++ return offset;
++}
++
++/*
++ * timer_interrupt() needs to keep up the real-time clock,
++ * as well as call the "do_timer()" routine every clocktick
++ */
++irqreturn_t timer_interrupt(int irq, void *dummy)
++{
++ /* last time the cmos clock got updated */
++ static long last_rtc_update=0;
++
++ write_seqlock(&xtime_lock);
++ na_timer0->np_timerstatus = 0; /* Clear the interrupt condition */
++
++ do_timer(1);
++#ifndef CONFIG_SMP
++ update_process_times(user_mode(get_irq_regs()));
++#endif
++ profile_tick(CPU_PROFILING);
++ /*
++ * If we have an externally synchronized Linux clock, then update
++ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
++ * called as close as possible to 500 ms before the new second starts.
++ */
++ if (ntp_synced() &&
++ xtime.tv_sec > last_rtc_update + 660 &&
++ (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
++ (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
++ if (set_rtc_mmss(xtime.tv_sec) == 0)
++ last_rtc_update = xtime.tv_sec;
++ else
++ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
++ }
++
++ write_sequnlock(&xtime_lock);
++ return(IRQ_HANDLED);
++}
++
++void __init time_init(void)
++{
++ unsigned int year, mon, day, hour, min, sec;
++ int err;
++
++ extern void arch_gettod(int *year, int *mon, int *day, int *hour,
++ int *min, int *sec);
++
++ cpu_khz=nasys_clock_freq_1000;
++ arch_gettod(&year, &mon, &day, &hour, &min, &sec);
++
++ if ((year += 1900) < 1970)
++ year += 100;
++ xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
++ xtime.tv_nsec = 0;
++ wall_to_monotonic.tv_sec = -xtime.tv_sec;
++
++ err = request_irq(na_timer0_irq, timer_interrupt, IRQ_FLG_LOCK, "timer", NULL);
++ if(err)
++ printk(KERN_ERR "%s() failed - errno = %d\n", __FUNCTION__, -err);
++ na_timer0->np_timerperiodl = (nasys_clock_freq/HZ)-1;
++ na_timer0->np_timerperiodh = ((nasys_clock_freq/HZ)-1) >> 16;
++
++ /* interrupt enable + continuous + start */
++ na_timer0->np_timercontrol = np_timercontrol_start_mask
++ + np_timercontrol_cont_mask
++ + np_timercontrol_ito_mask;
++}
++
++/*
++ * This version of gettimeofday has near microsecond resolution.
++ */
++void do_gettimeofday(struct timeval *tv)
++{
++ unsigned long flags;
++ unsigned long seq;
++ unsigned long usec, sec;
++
++ do {
++ seq = read_seqbegin_irqsave(&xtime_lock, flags);
++ usec = gettimeoffset();
++ sec = xtime.tv_sec;
++ usec += (xtime.tv_nsec / 1000);
++ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
++
++ while (usec >= 1000000) {
++ usec -= 1000000;
++ sec++;
++ }
++
++ tv->tv_sec = sec;
++ tv->tv_usec = usec;
++}
++EXPORT_SYMBOL(do_gettimeofday);
++
++int do_settimeofday(struct timespec *tv)
++{
++ time_t wtm_sec, sec = tv->tv_sec;
++ long wtm_nsec, nsec = tv->tv_nsec;
++
++ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
++ return -EINVAL;
++
++ write_seqlock_irq(&xtime_lock);
++ /*
++ * This is revolting. We need to set "xtime" correctly. However, the
++ * value in this location is the value at the last tick.
++ * Discover what correction gettimeofday() would have
++ * made, and then undo it!
++ */
++ nsec -= gettimeoffset() * NSEC_PER_USEC;
++
++ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
++ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
++
++ set_normalized_timespec(&xtime, sec, nsec);
++ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
++
++ ntp_clear();
++
++ write_sequnlock_irq(&xtime_lock);
++ clock_was_set();
++
++ return 0;
++}
++EXPORT_SYMBOL(do_settimeofday);
++
++/*
++ * Scheduler clock - returns current time in nanosec units.
++ */
++unsigned long long sched_clock(void)
++{
++ return (unsigned long long)jiffies * (1000000000 / HZ);
++}
+diff --git a/arch/nios2nommu/kernel/traps.c b/arch/nios2nommu/kernel/traps.c
+new file mode 100644
+index 0000000..14b7e4c
+--- /dev/null
++++ b/arch/nios2nommu/kernel/traps.c
+@@ -0,0 +1,178 @@
++/*
++ * arch/niosnommu/kernel/traps.c
++ *
++ * Copyright 2004 Microtronix Datacom Ltd.
++ * Copyright 2001 Vic Phillips
++ * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * hacked from:
++ *
++ * arch/sparcnommu/kernel/traps.c
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/sched.h> /* for jiffies */
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/module.h>
++
++#include <asm/delay.h>
++#include <asm/system.h>
++#include <asm/ptrace.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/unistd.h>
++
++#include <asm/nios.h>
++
++/* #define TRAP_DEBUG */
++
++#if 0
++void dumpit(unsigned long l1, unsigned long l2)
++{
++ printk("0x%08x l1 0x%08x l2\n");
++ while(1);
++}
++
++struct trap_trace_entry {
++ unsigned long pc;
++ unsigned long type;
++};
++
++int trap_curbuf = 0;
++struct trap_trace_entry trapbuf[1024];
++
++void syscall_trace_entry(struct pt_regs *regs)
++{
++ printk("%s[%d]: ", current->comm, current->pid);
++ printk("scall<%d> (could be %d)\n", (int) regs->r3,
++ (int) regs->r4);
++}
++
++void syscall_trace_exit(struct pt_regs *regs)
++{
++}
++#endif
++
++/*
++ * The architecture-independent backtrace generator
++ */
++void dump_stack(void)
++{
++ unsigned long stack;
++
++ show_stack(current, &stack);
++}
++
++EXPORT_SYMBOL(dump_stack);
++
++/*
++ * The show_stack is an external API which we do not use ourselves.
++ * The oops is printed in die_if_kernel.
++ */
++
++int kstack_depth_to_print = 48;
++
++void show_stack(struct task_struct *task, unsigned long *stack)
++{
++ unsigned long *endstack, addr;
++ extern char _start, _etext;
++ int i;
++
++ if (!stack) {
++ if (task)
++ stack = (unsigned long *)task->thread.ksp;
++ else
++ stack = (unsigned long *)&stack;
++ }
++
++ addr = (unsigned long) stack;
++ endstack = (unsigned long *) PAGE_ALIGN(addr);
++
++ printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
++ for (i = 0; i < kstack_depth_to_print; i++) {
++ if (stack + 1 > endstack)
++ break;
++ if (i % 8 == 0)
++ printk(KERN_EMERG "\n ");
++ printk(KERN_EMERG " %08lx", *stack++);
++ }
++
++ printk(KERN_EMERG "\nCall Trace:");
++ i = 0;
++ while (stack + 1 <= endstack) {
++ addr = *stack++;
++ /*
++ * If the address is either in the text segment of the
++ * kernel, or in the region which contains vmalloc'ed
++ * memory, it *may* be the address of a calling
++ * routine; if so, print it so that someone tracing
++ * down the cause of the crash will be able to figure
++ * out the call path that was taken.
++ */
++ if (((addr >= (unsigned long) &_start) &&
++ (addr <= (unsigned long) &_etext))) {
++ if (i % 4 == 0)
++ printk(KERN_EMERG "\n ");
++ printk(KERN_EMERG " [<%08lx>]", addr);
++ i++;
++ }
++ }
++ printk(KERN_EMERG "\n");
++}
++
++void die_if_kernel(char *str, struct pt_regs *pregs)
++{
++ unsigned long pc;
++
++ pc = pregs->ra;
++ printk("0x%08lx\n trapped to die_if_kernel\n",pregs->ra);
++ show_regs(pregs);
++ if(pregs->status_extension & PS_S)
++ do_exit(SIGKILL);
++ do_exit(SIGSEGV);
++}
++
++void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
++{
++ if(type < 0x10) {
++ printk("Unimplemented Nios2 TRAP, type = %02lx\n", type);
++ die_if_kernel("Whee... Hello Mr. Penguin", current->thread.kregs);
++ }
++}
++
++#if 0
++void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long psr)
++{
++#ifdef TRAP_DEBUG
++ printk("Watchpoint detected at PC %08lx PSR %08lx\n", pc, psr);
++#endif
++ if(psr & PSR_SUPERVISOR)
++ panic("Tell me what a watchpoint trap is, and I'll then deal "
++ "with such a beast...");
++}
++#endif
++
++void trap_init(void)
++{
++#ifdef DEBUG
++ printk("trap_init reached\n");
++#endif
++}
+diff --git a/arch/nios2nommu/kernel/usb.c b/arch/nios2nommu/kernel/usb.c
+new file mode 100644
+index 0000000..65655b6
+--- /dev/null
++++ b/arch/nios2nommu/kernel/usb.c
+@@ -0,0 +1,341 @@
++/*
++ * arch/nios2nommu/kernel/usb.c -- platform level USB initialization
++ *
++ * 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
++ */
++
++#undef DEBUG
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/nios.h>
++
++#if defined(CONFIG_USB_SL811_HCD) || defined (CONFIG_USB_SL811_HCD_MODULE)
++#if defined(CONFIG_MICROTRONIX_STRATIX) || defined (CONFIG_MICROTRONIX_CYCLONE)
++
++#include <linux/usb/sl811.h>
++#define SL811_ADDR ((unsigned int)na_usb)
++#define SL811_IRQ na_usb_irq
++
++static void sl811_port_power(struct device *dev, int is_on)
++{
++}
++
++static void sl811_port_reset(struct device *dev)
++{
++ writeb(0xA, (SL811_ADDR+8));
++ mdelay(10);
++ writeb(4, (SL811_ADDR+8));
++}
++
++static struct resource sl811hs_resources[] = {
++ {
++ .start = (SL811_ADDR),
++ .end = (SL811_ADDR + 3),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = (SL811_ADDR + 4),
++ .end = (SL811_ADDR + 7),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = SL811_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct sl811_platform_data sl811_data = {
++ .can_wakeup = 0,
++ .potpg = 0,
++ .power = 250,
++ .port_power = sl811_port_power,
++ .reset = sl811_port_reset,
++};
++
++static struct platform_device sl811hs_device = {
++ .name = "sl811-hcd",
++ .id = -1,
++ .dev = {
++ //.release = usb_release,
++ //.dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0x0fffffff,
++ .platform_data = &sl811_data,
++ },
++ .num_resources = ARRAY_SIZE(sl811hs_resources),
++ .resource = sl811hs_resources,
++};
++
++
++static int __init mtx_kit_usb_init(void)
++{
++ int status;
++
++ status = platform_device_register(&sl811hs_device);
++ if (status) {
++ pr_debug("can't register sl811hs device, %d\n", status);
++ return -1;
++ }
++
++ writeb(4, (SL811_ADDR+8));
++ return 0;
++}
++
++subsys_initcall(mtx_kit_usb_init);
++#endif /* (CONFIG_MICROTRONIX_STRATIX) || (CONFIG_MICROTRONIX_CYCLONE)*/
++#endif /*(CONFIG_USB_SL811_HCD) ||(CONFIG_USB_SL811_HCD_MODULE) */
++
++#if defined(CONFIG_USB_ISP116X_HCD) || defined (CONFIG_USB_ISP116X_HCD_MODULE)
++
++#include <linux/usb/isp116x.h>
++
++#define ISP116X_HCD_ADDR ((unsigned int)na_usb)
++#define ISP116X_HCD_IRQ na_usb_irq
++
++static void isp116x_delay(struct device *dev, int delay)
++{
++ ndelay(delay);
++}
++
++static struct resource isp116x_hcd_resources[] = {
++ {
++ .start = (ISP116X_HCD_ADDR),
++ .end = (ISP116X_HCD_ADDR + 3),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = (ISP116X_HCD_ADDR + 4),
++ .end = (ISP116X_HCD_ADDR + 7),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = ISP116X_HCD_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct isp116x_platform_data isp116x_data = {
++ // Enable internal resistors on downstream ports
++ .sel15Kres = 1,
++ // On-chip overcurrent protection
++ .oc_enable = 1,
++ // INT output polarity
++ .int_act_high = 0,
++ // INT edge or level triggered
++ .int_edge_triggered = 0,
++ // Wakeup by devices on usb bus enabled
++ .remote_wakeup_enable = 0,
++ .delay = isp116x_delay,
++};
++
++static struct platform_device isp116x_hcd = {
++ .name = "isp116x-hcd",
++ .id = -1,
++ .dev = {
++ //.release = usb_release,
++ //.dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0x0fffffff,
++ .platform_data = &isp116x_data,
++ },
++ .num_resources = ARRAY_SIZE(isp116x_hcd_resources),
++ .resource = isp116x_hcd_resources,
++};
++
++static int __init usb_hcd_init(void)
++{
++ int status;
++
++ status = platform_device_register(&isp116x_hcd);
++ if (status) {
++ pr_debug("can't register isp116x host controller, %d\n", status);
++ return -1;
++ }
++
++ return 0;
++}
++subsys_initcall(usb_hcd_init);
++#endif /*(CONFIG_USB_ISP116X_HCD) ||(CONFIG_USB_ISP116X_HCD_MODULE) */
++
++#if defined(CONFIG_USB_ISP1161X) || defined(CONFIG_USB_ISP1161X_MODULE)
++#include <linux/usb_isp116x_dc.h>
++
++#define ISP116X_UDC_ADDR ((unsigned int)na_usb+8)
++#define ISP116X_UDC_IRQ na_int2_usb_irq
++
++static struct resource isp116x_udc_resources[] = {
++ {
++ .start = (ISP116X_UDC_ADDR),
++ .end = (ISP116X_UDC_ADDR + 3),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = (ISP116X_UDC_ADDR + 4),
++ .end = (ISP116X_UDC_ADDR + 7),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = ISP116X_UDC_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++static void isp116x_udc_delay()
++{
++ __asm__ __volatile__(
++ "1: \n\t"
++ " beq %0,zero,2f\n\t"
++ " addi %0, %0, -1\n\t"
++ " br 1b\n\t"
++ "2: \n\t"
++ :
++ : "r" (nasys_clock_freq_1000 * 180 / 2000000)
++ );
++
++}
++struct isp116x_dc_platform_data isp116x_udc_data = {
++ .ext_pullup_enable =0,
++ .no_lazy =1,
++ .eot_act_high =0,
++ .remote_wakeup_enable=1,
++ .power_off_enable =1,
++ .int_edge_triggered =0,
++ .int_act_high =0,
++ .clkout_freq =12,
++ .delay = isp116x_udc_delay
++};
++
++static struct platform_device isp116x_udc = {
++ .name = "isp1161a_udc",
++ .id = -1,
++ .dev = {
++ //.release = usb_release,
++ //.dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0x0fffffff,
++ .platform_data = &isp116x_udc_data,
++ },
++ .num_resources = ARRAY_SIZE(isp116x_udc_resources),
++ .resource = isp116x_udc_resources,
++};
++
++static int __init usb_udc_init(void)
++{
++ int status;
++ np_pio* pio;
++
++ status = platform_device_register(&isp116x_udc);
++ if (status) {
++ pr_debug("can't register isp116x device controller, %d\n", status);
++ return -1;
++ }
++
++ /* enable interrupts */
++ pio = (np_pio*)na_int2_usb;
++ //outw(0, &pio->np_piodata);
++ //outw(0, &pio->np_pioedgecapture);
++ outw(1, &pio->np_piointerruptmask);
++
++ return 0;
++}
++subsys_initcall(usb_udc_init);
++#endif
++
++#if defined(na_ISP1362_avalonS) // for DE2 dev board, FIX ME otehrwise
++#define na_usb na_ISP1362_avalonS
++#define na_usb_irq na_ISP1362_avalonS_irq
++#endif
++
++#if defined(na_ISP1362_avalon_slave_0) // for DE2 dev board, FIX ME otehrwise
++#define na_usb na_ISP1362_avalon_slave_0
++#define na_usb_irq na_ISP1362_avalon_slave_0_irq
++#endif
++
++#if defined(CONFIG_USB_ISP1362_HCD) && defined(na_usb)
++
++#include <linux/usb_isp1362.h>
++#define ISP1362_HCD_ADDR ((unsigned int)na_usb)
++#define ISP1362_HCD_IRQ na_usb_irq
++
++static struct resource isp1362_hcd_resources[] = {
++ {
++ .start = (ISP1362_HCD_ADDR),
++ .end = (ISP1362_HCD_ADDR + 3),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = (ISP1362_HCD_ADDR + 4),
++ .end = (ISP1362_HCD_ADDR + 7),
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = ISP1362_HCD_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct isp1362_platform_data isp1362_data = {
++ // Enable internal resistors on downstream ports
++ .sel15Kres = 1,
++ // Clock cannot be stopped
++ .clknotstop = 0,
++ // On-chip overcurrent protection
++ .oc_enable = 0,
++ // INT output polarity
++ .int_act_high = 0,
++ // INT edge or level triggered
++ .int_edge_triggered = 0,
++ // WAKEUP pin connected
++ .remote_wakeup_connected = 0,
++ // Switch or not to switch (keep always powered)
++ .no_power_switching = 1,
++ // Ganged port power switching (0) or individual port power switching (1)
++ .power_switching_mode = 0,
++};
++
++static struct platform_device isp1362_hcd = {
++ .name = "isp1362-hcd",
++ .id = -1,
++ .dev = {
++ //.release = usb_release,
++ //.dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0x0fffffff,
++ .platform_data = &isp1362_data,
++ },
++ .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
++ .resource = isp1362_hcd_resources,
++};
++
++static int __init usb_hcd_init(void)
++{
++ int status;
++
++ status = platform_device_register(&isp1362_hcd);
++ if (status) {
++ pr_debug("can't register isp1362 host controller, %d\n", status);
++ return -1;
++ }
++
++ return 0;
++}
++subsys_initcall(usb_hcd_init);
++#endif
++
+diff --git a/arch/nios2nommu/kernel/vmlinux.lds.S b/arch/nios2nommu/kernel/vmlinux.lds.S
+new file mode 100644
+index 0000000..491901c
+--- /dev/null
++++ b/arch/nios2nommu/kernel/vmlinux.lds.S
+@@ -0,0 +1,141 @@
++#include <asm-generic/vmlinux.lds.h>
++#include <asm/nios.h>
++
++OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
++
++OUTPUT_ARCH(nios)
++ENTRY(_start) /* Defined in head.S */
++
++jiffies = jiffies_64;
++
++SECTIONS
++{
++ . = nasys_program_mem;
++ /* read-only */
++ _stext = . ;
++ _text = .; /* Text and read-only data */
++ .text : {
++ TEXT_TEXT
++ SCHED_TEXT
++ LOCK_TEXT
++ *(.fixup)
++ *(.gnu.warning)
++ } =0
++
++ . = ALIGN(4) ;
++ _etext = .; /* End of text section */
++
++ . = ALIGN(32); /* Exception table */
++ __start___ex_table = .;
++ __ex_table : { *(__ex_table) }
++ __stop___ex_table = .;
++
++ RODATA
++
++ /* writeable */
++ .data : { /* Data */
++ /*
++ * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which
++ * limits the maximum alignment to at most 32kB and results in the following
++ * warning:
++ *
++ * CC arch/mips/kernel/init_task.o
++ * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’
++ * is greater than maximum object file alignment. Using 32768
++ */
++ . = ALIGN(4096);
++ *(.data.init_task)
++
++ *(.data)
++
++ CONSTRUCTORS
++ }
++
++ .lit8 : { *(.lit8) }
++ .lit4 : { *(.lit4) }
++ /* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .sdata : { *(.sdata) }
++
++ . = ALIGN(4096);
++ __nosave_begin = .;
++ .data_nosave : { *(.data.nosave) }
++ . = ALIGN(4096);
++ __nosave_end = .;
++
++ . = ALIGN(32);
++ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
++
++ _edata = .; /* End of data section */
++
++ /* will be freed after init */
++ . = ALIGN(4096); /* Init code and data */
++ __init_begin = .;
++ .init.text : {
++ _sinittext = .;
++ *(.init.text)
++ _einittext = .;
++ }
++ .init.data : { *(.init.data) }
++ . = ALIGN(16);
++ __setup_start = .;
++ .init.setup : { *(.init.setup) }
++ __setup_end = .;
++
++ __initcall_start = .;
++ .initcall.init : {
++ INITCALLS
++ }
++ __initcall_end = .;
++
++ __con_initcall_start = .;
++ .con_initcall.init : { *(.con_initcall.init) }
++ __con_initcall_end = .;
++ SECURITY_INIT
++ /* .exit.text is discarded at runtime, not link time, to deal with
++ references from .rodata */
++ .exit.text : { *(.exit.text) }
++ .exit.data : { *(.exit.data) }
++ . = ALIGN(4096);
++ __initramfs_start = .;
++ .init.ramfs : { *(.init.ramfs) }
++ __initramfs_end = .;
++ . = ALIGN(32);
++ __per_cpu_start = .;
++ .data.percpu : { *(.data.percpu) }
++ __per_cpu_end = .;
++ . = ALIGN(4096);
++ __init_end = .;
++ /* freed after init ends here */
++
++ __bss_start = .; /* BSS */
++ .sbss : {
++ *(.sbss)
++ *(.scommon)
++ }
++ .bss : {
++ *(.bss)
++ *(COMMON)
++ }
++ __bss_stop = .;
++
++ _end = . ;
++
++ /* Sections to be discarded */
++ /DISCARD/ : {
++ *(.exit.text)
++ *(.exit.data)
++ *(.exitcall.exit)
++ }
++
++
++ STABS_DEBUG
++
++ DWARF_DEBUG
++
++ /* These must appear regardless of . */
++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
++ .note : { *(.note) }
++}
+diff --git a/arch/nios2nommu/lib/Makefile b/arch/nios2nommu/lib/Makefile
+new file mode 100644
+index 0000000..1315c57
+--- /dev/null
++++ b/arch/nios2nommu/lib/Makefile
+@@ -0,0 +1,17 @@
++#
++# Copyright (C) 2005 Microtronix Datacom Ltd
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This 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 Library General Public License for more
++# details.
++
++####CSRC := $(wildcard *.c)
++####lib-y =$(patsubst %.c,%.o, $(CSRC))
++####wapos!
++lib-y =checksum.o string.o memcpy.o
+diff --git a/arch/nios2nommu/lib/checksum.c b/arch/nios2nommu/lib/checksum.c
+new file mode 100644
+index 0000000..475f1a3
+--- /dev/null
++++ b/arch/nios2nommu/lib/checksum.c
+@@ -0,0 +1,73 @@
++/*--------------------------------------------------------------------
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <net/checksum.h>
++#include <asm/checksum.h>
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * computes the checksum of a memory block at buff, length len,
++ * and adds in "sum" (32-bit)
++ *
++ * returns a 32-bit number suitable for feeding into itself
++ * or csum_tcpudp_magic
++ *
++ * this function must be called with even lengths, except
++ * for the last fragment, which may be odd
++ *
++ * it's best to have buff aligned on a 32-bit boundary
++ */
++
++unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
++{
++#if 0
++ __asm__ __volatile__ ...//;dgt2;tmp;not (yet) available...
++ ...//;dgt2;tmp;NiosI didn't offer either...
++#else
++ unsigned int result = do_csum(buff, len);
++
++ /* add in old sum, and carry.. */
++ result += sum;
++ if (sum > result)
++ result += 1;
++ return result;
++#endif
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/*
++ * the same as csum_partial, but copies from fs:src while it
++ * checksums
++ *
++ * here even more important to align src and dst on a 32-bit (or even
++ * better 64-bit) boundary
++ */
++
++unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum)
++{
++ memcpy(dst, src, len);
++ return csum_partial(dst, len, sum);
++
++}
+diff --git a/arch/nios2nommu/lib/memcpy.c b/arch/nios2nommu/lib/memcpy.c
+new file mode 100644
+index 0000000..6586b99
+--- /dev/null
++++ b/arch/nios2nommu/lib/memcpy.c
+@@ -0,0 +1,62 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/lib/memcpy.c
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jun/09/2004 dgt Split out separate source file from string.c
++ *
++ ---------------------------------------------------------------------*/
++
++#include <linux/types.h>
++#include <linux/autoconf.h>
++#include <asm/nios.h>
++#include <asm/string.h>
++
++#ifdef __HAVE_ARCH_MEMCPY
++ void * memcpy(void * d, const void * s, size_t count)
++ {
++ unsigned long dst, src;
++ dst = (unsigned long) d;
++ src = (unsigned long) s;
++
++ if ((count < 8) || ((dst ^ src) & 3))
++ goto restup;
++
++ if (dst & 1) {
++ *(char*)dst++=*(char*)src++;
++ count--;
++ }
++ if (dst & 2) {
++ *(short*)dst=*(short*)src;
++ src += 2;
++ dst += 2;
++ count -= 2;
++ }
++ while (count > 3) {
++ *(long*)dst=*(long*)src;
++ src += 4;
++ dst += 4;
++ count -= 4;
++ }
++
++ restup:
++ while (count--)
++ *(char*)dst++=*(char*)src++;
++
++ return d;
++ }
++#endif
+diff --git a/arch/nios2nommu/lib/string.c b/arch/nios2nommu/lib/string.c
+new file mode 100644
+index 0000000..b87c195
+--- /dev/null
++++ b/arch/nios2nommu/lib/string.c
+@@ -0,0 +1,180 @@
++/*--------------------------------------------------------------------
++ *
++ * arch/nios2nommu/lib/string.c
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ * Jun/09/2004 dgt Split out memcpy into separate source file
++ *
++ ---------------------------------------------------------------------*/
++
++#include <linux/types.h>
++#include <linux/autoconf.h>
++#include <asm/nios.h>
++#include <asm/string.h>
++
++#ifdef __HAVE_ARCH_MEMSET
++void * memset(void * s,int c,size_t count)
++{
++
++ if (count > 8) {
++ int destptr, charcnt, dwordcnt, fill8reg, wrkrega;
++ __asm__ __volatile__ (
++ // fill8 %3, %5 (c & 0xff)\n\t"
++ //
++ " slli %4, %5, 8\n\t"
++ " or %4, %4, %5\n\t"
++ " slli %3, %4, 16\n\t"
++ " or %3, %3, %4\n\t"
++ //
++ // Word-align %0 (s) if necessary
++ //
++ " andi %4, %0, 0x01\n\t"
++ " beq %4, zero, 1f\n\t"
++ " addi %1, %1, -1\n\t"
++ " stb %3, 0(%0)\n\t"
++ " addi %0, %0, 1\n\t"
++ "1: \n\t"
++ " mov %2, %1\n\t"
++ //
++ // Dword-align %0 (s) if necessary
++ //
++ " andi %4, %0, 0x02\n\t"
++ " beq %4, zero, 2f\n\t"
++ " addi %1, %1, -2\n\t"
++ " sth %3, 0(%0)\n\t"
++ " addi %0, %0, 2\n\t"
++ " mov %2, %1\n\t"
++ "2: \n\t"
++ // %1 and %2 are how many more bytes to set
++ //
++ " srli %2, %2, 2\n\t"
++ //
++ // %2 is how many dwords to set
++ //
++ "3: ;\n\t"
++ " stw %3, 0(%0)\n\t"
++ " addi %0, %0, 4\n\t"
++ " addi %2, %2, -1\n\t"
++ " bne %2, zero, 3b\n\t"
++ //
++ // store residual word and/or byte if necessary
++ //
++ " andi %4, %1, 0x02\n\t"
++ " beq %4, zero, 4f\n\t"
++ " sth %3, 0(%0)\n\t"
++ " addi %0, %0, 2\n\t"
++ "4: \n\t"
++ // store residual byte if necessary
++ //
++ " andi %4, %1, 0x01\n\t"
++ " beq %4, zero, 5f\n\t"
++ " stb %3, 0(%0)\n\t"
++ "5: \n\t"
++
++ : "=r" (destptr), /* %0 Output */
++ "=r" (charcnt), /* %1 Output */
++ "=r" (dwordcnt), /* %2 Output */
++ "=r" (fill8reg), /* %3 Output */
++ "=r" (wrkrega) /* %4 Output */
++
++ : "r" (c & 0xff), /* %5 Input */
++ "0" (s), /* %0 Input/Output */
++ "1" (count) /* %1 Input/Output */
++
++ : "memory" /* clobbered */
++ );
++ }
++ else {
++ char* xs=(char*)s;
++ while (count--)
++ *xs++ = c;
++ }
++ return s;
++}
++#endif
++
++#ifdef __HAVE_ARCH_MEMMOVE
++void * memmove(void * d, const void * s, size_t count)
++{
++ unsigned long dst, src;
++
++ if (d < s) {
++ dst = (unsigned long) d;
++ src = (unsigned long) s;
++
++ if ((count < 8) || ((dst ^ src) & 3))
++ goto restup;
++
++ if (dst & 1) {
++ *(char*)dst++=*(char*)src++;
++ count--;
++ }
++ if (dst & 2) {
++ *(short*)dst=*(short*)src;
++ src += 2;
++ dst += 2;
++ count -= 2;
++ }
++ while (count > 3) {
++ *(long*)dst=*(long*)src;
++ src += 4;
++ dst += 4;
++ count -= 4;
++ }
++
++ restup:
++ while (count--)
++ *(char*)dst++=*(char*)src++;
++ } else {
++ dst = (unsigned long) d + count;
++ src = (unsigned long) s + count;
++
++ if ((count < 8) || ((dst ^ src) & 3))
++ goto restdown;
++
++ if (dst & 1) {
++ src--;
++ dst--;
++ count--;
++ *(char*)dst=*(char*)src;
++ }
++ if (dst & 2) {
++ src -= 2;
++ dst -= 2;
++ count -= 2;
++ *(short*)dst=*(short*)src;
++ }
++ while (count > 3) {
++ src -= 4;
++ dst -= 4;
++ count -= 4;
++ *(long*)dst=*(long*)src;
++ }
++
++ restdown:
++ while (count--) {
++ src--;
++ dst--;
++ *(char*)dst=*(char*)src;
++ }
++ }
++
++ return d;
++
++}
++#endif
+diff --git a/arch/nios2nommu/mm/Makefile b/arch/nios2nommu/mm/Makefile
+new file mode 100644
+index 0000000..b007a11
+--- /dev/null
++++ b/arch/nios2nommu/mm/Makefile
+@@ -0,0 +1,12 @@
++# $Id: Makefile,v 1.1 2006/07/05 06:23:18 gerg Exp $
++# Makefile for the linux Sparc-specific parts of the memory manager.
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++obj-y := init.o ioremap.o extable.o memory.o
++obj-y += dma-noncoherent.o
++
+diff --git a/arch/nios2nommu/mm/dma-noncoherent.c b/arch/nios2nommu/mm/dma-noncoherent.c
+new file mode 100644
+index 0000000..5649940
+--- /dev/null
++++ b/arch/nios2nommu/mm/dma-noncoherent.c
+@@ -0,0 +1,373 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
++ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
++ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
++ */
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/cache.h>
++#include <asm/cacheflush.h>
++#include <asm/io.h>
++
++#define UNCAC_ADDR(addr) ((void *)((unsigned long)(addr) | 0x80000000))
++#define CAC_ADDR(addr) ((void *)((unsigned long)(addr) & ~0x80000000))
++
++/*
++ * Warning on the terminology - Linux calls an uncached area coherent;
++ * MIPS terminology calls memory areas with hardware maintained coherency
++ * coherent.
++ */
++
++void *dma_alloc_noncoherent(struct device *dev, size_t size,
++ dma_addr_t * dma_handle, gfp_t gfp)
++{
++ void *ret;
++ /* ignore region specifiers */
++ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
++
++ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
++ gfp |= GFP_DMA;
++ ret = (void *) __get_free_pages(gfp, get_order(size));
++
++ if (ret != NULL) {
++ memset(ret, 0, size);
++ *dma_handle = virt_to_phys(ret);
++ }
++
++ return ret;
++}
++
++EXPORT_SYMBOL(dma_alloc_noncoherent);
++
++void *dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t * dma_handle, gfp_t gfp)
++{
++ void *ret;
++
++ ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
++ if (ret) {
++ dma_cache_wback_inv((unsigned long) ret, size);
++ ret = UNCAC_ADDR(ret);
++ }
++
++ return ret;
++}
++
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
++ dma_addr_t dma_handle)
++{
++ free_pages((unsigned long) vaddr, get_order(size));
++}
++
++EXPORT_SYMBOL(dma_free_noncoherent);
++
++void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
++ dma_addr_t dma_handle)
++{
++ unsigned long addr = (unsigned long) vaddr;
++
++ addr = (unsigned long) CAC_ADDR(addr);
++ free_pages(addr, get_order(size));
++}
++
++EXPORT_SYMBOL(dma_free_coherent);
++
++static inline void __dma_sync(unsigned long addr, size_t size,
++ enum dma_data_direction direction)
++{
++ switch (direction) {
++ case DMA_TO_DEVICE:
++ dma_cache_wback(addr, size);
++ break;
++
++ case DMA_FROM_DEVICE:
++ dma_cache_inv(addr, size);
++ break;
++
++ case DMA_BIDIRECTIONAL:
++ dma_cache_wback_inv(addr, size);
++ break;
++
++ default:
++ BUG();
++ }
++}
++
++dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
++ enum dma_data_direction direction)
++{
++ unsigned long addr = (unsigned long) ptr;
++
++ __dma_sync(addr, size, direction);
++
++ return virt_to_phys(ptr);
++}
++
++EXPORT_SYMBOL(dma_map_single);
++
++void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ unsigned long addr;
++ addr = dma_addr + PAGE_OFFSET;
++
++ //__dma_sync(addr, size, direction);
++}
++
++EXPORT_SYMBOL(dma_unmap_single);
++
++int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ int i;
++
++ BUG_ON(direction == DMA_NONE);
++
++ for (i = 0; i < nents; i++, sg++) {
++ unsigned long addr;
++
++ addr = (unsigned long) page_address(sg->page);
++ if (addr) {
++ __dma_sync(addr + sg->offset, sg->length, direction);
++ sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
++ + sg->offset;
++ }
++ }
++
++ return nents;
++}
++
++EXPORT_SYMBOL(dma_map_sg);
++
++dma_addr_t dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size, enum dma_data_direction direction)
++{
++ unsigned long addr;
++
++ BUG_ON(direction == DMA_NONE);
++
++ addr = (unsigned long) page_address(page) + offset;
++ dma_cache_wback_inv(addr, size);
++
++ return page_to_phys(page) + offset;
++}
++
++EXPORT_SYMBOL(dma_map_page);
++
++void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(direction == DMA_NONE);
++
++ if (direction != DMA_TO_DEVICE) {
++ unsigned long addr;
++
++ addr = dma_address + PAGE_OFFSET;
++ dma_cache_wback_inv(addr, size);
++ }
++}
++
++EXPORT_SYMBOL(dma_unmap_page);
++
++void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ unsigned long addr;
++ int i;
++
++ BUG_ON(direction == DMA_NONE);
++
++ if (direction == DMA_TO_DEVICE)
++ return;
++
++ for (i = 0; i < nhwentries; i++, sg++) {
++ addr = (unsigned long) page_address(sg->page);
++ if (addr)
++ __dma_sync(addr + sg->offset, sg->length, direction);
++ }
++}
++
++EXPORT_SYMBOL(dma_unmap_sg);
++
++void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
++ size_t size, enum dma_data_direction direction)
++{
++ unsigned long addr;
++
++ BUG_ON(direction == DMA_NONE);
++
++ addr = dma_handle + PAGE_OFFSET;
++ __dma_sync(addr, size, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_single_for_cpu);
++
++void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
++ size_t size, enum dma_data_direction direction)
++{
++ unsigned long addr;
++
++ BUG_ON(direction == DMA_NONE);
++
++ addr = dma_handle + PAGE_OFFSET;
++ __dma_sync(addr, size, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_single_for_device);
++
++void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size, enum dma_data_direction direction)
++{
++ unsigned long addr;
++
++ BUG_ON(direction == DMA_NONE);
++
++ addr = dma_handle + offset + PAGE_OFFSET;
++ __dma_sync(addr, size, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
++
++void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size, enum dma_data_direction direction)
++{
++ unsigned long addr;
++
++ BUG_ON(direction == DMA_NONE);
++
++ addr = dma_handle + offset + PAGE_OFFSET;
++ __dma_sync(addr, size, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_single_range_for_device);
++
++void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ int i;
++
++ BUG_ON(direction == DMA_NONE);
++
++ /* Make sure that gcc doesn't leave the empty loop body. */
++ for (i = 0; i < nelems; i++, sg++)
++ __dma_sync((unsigned long)page_address(sg->page),
++ sg->length, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_sg_for_cpu);
++
++void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ int i;
++
++ BUG_ON(direction == DMA_NONE);
++
++ /* Make sure that gcc doesn't leave the empty loop body. */
++ for (i = 0; i < nelems; i++, sg++)
++ __dma_sync((unsigned long)page_address(sg->page),
++ sg->length, direction);
++}
++
++EXPORT_SYMBOL(dma_sync_sg_for_device);
++
++int dma_mapping_error(dma_addr_t dma_addr)
++{
++ return 0;
++}
++
++EXPORT_SYMBOL(dma_mapping_error);
++
++int dma_supported(struct device *dev, u64 mask)
++{
++ /*
++ * we fall back to GFP_DMA when the mask isn't all 1s,
++ * so we can't guarantee allocations that must be
++ * within a tighter range than GFP_DMA..
++ */
++ if (mask < 0x00ffffff)
++ return 0;
++
++ return 1;
++}
++
++EXPORT_SYMBOL(dma_supported);
++
++int dma_is_consistent(dma_addr_t dma_addr)
++{
++ return 1;
++}
++
++EXPORT_SYMBOL(dma_is_consistent);
++
++void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
++{
++ if (direction == DMA_NONE)
++ return;
++
++ dma_cache_wback_inv((unsigned long)vaddr, size);
++}
++
++EXPORT_SYMBOL(dma_cache_sync);
++
++/* The DAC routines are a PCIism.. */
++
++#ifdef CONFIG_PCI
++
++#include <linux/pci.h>
++
++dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
++ struct page *page, unsigned long offset, int direction)
++{
++ return (dma64_addr_t)page_to_phys(page) + offset;
++}
++
++EXPORT_SYMBOL(pci_dac_page_to_dma);
++
++struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
++ dma64_addr_t dma_addr)
++{
++ return mem_map + (dma_addr >> PAGE_SHIFT);
++}
++
++EXPORT_SYMBOL(pci_dac_dma_to_page);
++
++unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
++ dma64_addr_t dma_addr)
++{
++ return dma_addr & ~PAGE_MASK;
++}
++
++EXPORT_SYMBOL(pci_dac_dma_to_offset);
++
++void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
++ dma64_addr_t dma_addr, size_t len, int direction)
++{
++ BUG_ON(direction == PCI_DMA_NONE);
++
++ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
++}
++
++EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
++
++void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
++ dma64_addr_t dma_addr, size_t len, int direction)
++{
++ BUG_ON(direction == PCI_DMA_NONE);
++
++ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
++}
++
++EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
++
++#endif /* CONFIG_PCI */
+diff --git a/arch/nios2nommu/mm/extable.c b/arch/nios2nommu/mm/extable.c
+new file mode 100644
+index 0000000..e23778f
+--- /dev/null
++++ b/arch/nios2nommu/mm/extable.c
+@@ -0,0 +1,29 @@
++/*
++ * linux/arch/niosnommu/mm/extable.c
++ */
++
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <asm/uaccess.h>
++
++/* Simple binary search */
++const struct exception_table_entry *
++search_extable(const struct exception_table_entry *first,
++ const struct exception_table_entry *last,
++ unsigned long value)
++{
++ while (first <= last) {
++ const struct exception_table_entry *mid;
++ long diff;
++
++ mid = (last - first) / 2 + first;
++ diff = mid->insn - value;
++ if (diff == 0)
++ return mid;
++ else if (diff < 0)
++ first = mid+1;
++ else
++ last = mid-1;
++ }
++ return NULL;
++}
+diff --git a/arch/nios2nommu/mm/init.c b/arch/nios2nommu/mm/init.c
+new file mode 100644
+index 0000000..21fe61b
+--- /dev/null
++++ b/arch/nios2nommu/mm/init.c
+@@ -0,0 +1,231 @@
++/*
++ * linux/arch/nios2nommu/mm/init.c
++ *
++ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
++ * Kenneth Albanowski <kjahds@kjahds.com>,
++ * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * Based on:
++ *
++ * linux/arch/m68k/mm/init.c
++ *
++ * Copyright (C) 1995 Hamish Macdonald
++ *
++ * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
++ * DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
++ * Jan/20/2004 dgt NiosII
++ *
++ */
++
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++#include <linux/pagemap.h>
++#include <linux/bootmem.h>
++#include <linux/slab.h>
++
++#include <asm/setup.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++//;dgt2;#include <asm/machdep.h>
++//;dgt2;#include <asm/shglcore.h>
++
++#undef DEBUG
++
++extern void die_if_kernel(char *,struct pt_regs *,long);
++extern void free_initmem(void);
++
++/*
++ * BAD_PAGE is the page that is used for page faults when linux
++ * is out-of-memory. Older versions of linux just did a
++ * do_exit(), but using this instead means there is less risk
++ * for a process dying in kernel mode, possibly leaving a inode
++ * unused etc..
++ *
++ * BAD_PAGETABLE is the accompanying page-table: it is initialized
++ * to point to BAD_PAGE entries.
++ *
++ * ZERO_PAGE is a special page that is used for zero-initialized
++ * data and COW.
++ */
++static unsigned long empty_bad_page_table;
++
++static unsigned long empty_bad_page;
++
++unsigned long empty_zero_page;
++
++extern unsigned long rom_length;
++
++void show_mem(void)
++{
++ unsigned long i;
++ int free = 0, total = 0, reserved = 0, shared = 0;
++ int cached = 0;
++
++ printk(KERN_INFO "\nMem-info:\n");
++ show_free_areas();
++ i = max_mapnr;
++ while (i-- > 0) {
++ total++;
++ if (PageReserved(mem_map+i))
++ reserved++;
++ else if (PageSwapCache(mem_map+i))
++ cached++;
++ else if (!page_count(mem_map+i))
++ free++;
++ else
++ shared += page_count(mem_map+i) - 1;
++ }
++ printk(KERN_INFO "%d pages of RAM\n",total);
++ printk(KERN_INFO "%d free pages\n",free);
++ printk(KERN_INFO "%d reserved pages\n",reserved);
++ printk(KERN_INFO "%d pages shared\n",shared);
++ printk(KERN_INFO "%d pages swap cached\n",cached);
++}
++
++extern unsigned long memory_start;
++extern unsigned long memory_end;
++
++/*
++ * paging_init() continues the virtual memory environment setup which
++ * was begun by the code in arch/head.S.
++ * The parameters are pointers to where to stick the starting and ending
++ * addresses of available kernel virtual memory.
++ */
++void __init paging_init(void)
++{
++ /*
++ * Make sure start_mem is page aligned, otherwise bootmem and
++ * page_alloc get different views of the world.
++ */
++#ifdef DEBUG
++ unsigned long start_mem = PAGE_ALIGN(memory_start);
++#endif
++ unsigned long end_mem = memory_end & PAGE_MASK;
++
++#ifdef DEBUG
++ printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
++ start_mem, end_mem);
++#endif
++
++ /*
++ * Initialize the bad page table and bad page to point
++ * to a couple of allocated pages.
++ */
++ empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
++ empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
++ empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
++ memset((void *)empty_zero_page, 0, PAGE_SIZE);
++
++ /*
++ * Set up SFC/DFC registers (user data space).
++ */
++ set_fs (USER_DS);
++
++#ifdef DEBUG
++ printk (KERN_DEBUG "before free_area_init\n");
++
++ printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
++ start_mem, end_mem);
++#endif
++
++ {
++ unsigned long zones_size[MAX_NR_ZONES] = {0, };
++
++ zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
++ zones_size[ZONE_NORMAL] = 0;
++#ifdef CONFIG_HIGHMEM
++ zones_size[ZONE_HIGHMEM] = 0;
++#endif
++ free_area_init(zones_size);
++ }
++}
++
++void __init mem_init(void)
++{
++ int codek = 0, datak = 0, initk = 0;
++ unsigned long tmp;
++ extern char _etext, _stext, __init_begin, __init_end, _end;
++ unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
++ unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */
++
++#ifdef DEBUG
++ printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
++#endif
++
++ end_mem &= PAGE_MASK;
++ high_memory = (void *) end_mem;
++
++ start_mem = PAGE_ALIGN(start_mem);
++ max_mapnr = num_physpages = MAP_NR(high_memory);
++
++ /* this will put all memory onto the freelists */
++ totalram_pages = free_all_bootmem();
++
++ codek = (&_etext - &_stext) >> 10;
++ datak = (&_end - &_etext) >> 10;
++ initk = (&__init_begin - &__init_end) >> 10;
++
++ tmp = nr_free_pages() << PAGE_SHIFT;
++ printk(KERN_INFO "Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n",
++ tmp >> 10,
++ (&_end - &_stext) >> 10,
++ (rom_length > 0) ? ((rom_length >> 10) - codek) : 0,
++ rom_length >> 10,
++ codek,
++ datak
++ );
++}
++
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void __init free_initrd_mem(unsigned long start, unsigned long end)
++{
++ int pages = 0;
++ for (; start < end; start += PAGE_SIZE) {
++ ClearPageReserved(virt_to_page(start));
++ init_page_count(virt_to_page(start));
++ free_page(start);
++ totalram_pages++;
++ pages++;
++ }
++ printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
++}
++#endif
++
++void free_initmem(void)
++{
++#ifdef CONFIG_RAMKERNEL
++ unsigned long addr;
++ extern char __init_begin, __init_end;
++ /*
++ * The following code should be cool even if these sections
++ * are not page aligned.
++ */
++ addr = PAGE_ALIGN((unsigned long)(&__init_begin));
++ /* next to check that the page we free is not a partial page */
++ for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
++ ClearPageReserved(virt_to_page(addr));
++ init_page_count(virt_to_page(addr));
++ free_page(addr);
++ totalram_pages++;
++ }
++ printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
++ (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
++ (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
++ (int)(addr - PAGE_SIZE));
++#endif
++}
++
+diff --git a/arch/nios2nommu/mm/ioremap.c b/arch/nios2nommu/mm/ioremap.c
+new file mode 100644
+index 0000000..1c8b172
+--- /dev/null
++++ b/arch/nios2nommu/mm/ioremap.c
+@@ -0,0 +1,65 @@
++/* linux/arch/nios2nommu/mm/ioremap.c, based on:
++ *
++ * linux/arch/m68knommu/mm/kmap.c
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2000 Lineo, <davidm@lineo.com>
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/mm.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++
++#include <asm/setup.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/io.h>
++#include <asm/system.h>
++
++/*
++ * Map some physical address range into the kernel address space.
++ */
++
++void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
++{
++ return (void *)physaddr;
++}
++
++/*
++ * Unmap a ioremap()ed region again
++ */
++void iounmap(void *addr)
++{
++}
++
++/*
++ * __iounmap unmaps nearly everything, so be careful
++ * it doesn't free currently pointer/page tables anymore but it
++ * wans't used anyway and might be added later.
++ */
++void __iounmap(void *addr, unsigned long size)
++{
++}
++
+diff --git a/arch/nios2nommu/mm/memory.c b/arch/nios2nommu/mm/memory.c
+new file mode 100644
+index 0000000..76d60d9
+--- /dev/null
++++ b/arch/nios2nommu/mm/memory.c
+@@ -0,0 +1,212 @@
++/*
++ * linux/arch/nio2nommu/mm/memory.c
++ *
++ * Copyright (C) 1995 Hamish Macdonald
++ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
++ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * Based on:
++ *
++ * linux/arch/m68k/mm/memory.c
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/mm.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++
++#include <asm/setup.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/traps.h>
++#include <asm/io.h>
++
++/*
++ * cache_clear() semantics: Clear any cache entries for the area in question,
++ * without writing back dirty entries first. This is useful if the data will
++ * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
++ * _physical_ address.
++ */
++
++void cache_clear (unsigned long paddr, int len)
++{
++}
++
++
++/*
++ * Define cache invalidate functions. The instruction and data cache
++ * will need to be flushed. Write back the dirty data cache and invalidate
++ * the instruction cache for the range.
++ *
++ */
++
++static __inline__ void cache_invalidate_inst(unsigned long paddr, int len)
++{
++ unsigned long sset, eset;
++
++ sset = (paddr & (nasys_icache_size - 1)) & (~(nasys_icache_line_size - 1));
++ eset = (((paddr & (nasys_icache_size - 1)) + len) & (~(nasys_icache_line_size - 1))) + nasys_icache_line_size;
++
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushi %0\n\t"
++ "add %0,%0,%2\n\t"
++ "blt %0,%1,1b\n\t"
++ "flushp\n\t"
++ : : "r" (sset), "r" (eset), "r" (nasys_icache_line_size));
++
++}
++
++static __inline__ void cache_invalidate_data(unsigned long paddr, int len)
++{
++ unsigned long sset, eset;
++
++ sset = (paddr & (nasys_dcache_size - 1)) & (~(nasys_dcache_line_size - 1));
++ eset = (((paddr & (nasys_dcache_size - 1)) + len) & (~(nasys_dcache_line_size - 1))) + nasys_dcache_line_size;
++
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushd 0(%0)\n\t"
++ "add %0,%0,%2\n\t"
++ "blt %0,%1,1b\n\t"
++ : : "r" (sset),"r" (eset), "r" (nasys_dcache_line_size));
++
++}
++
++static __inline__ void cache_invalidate_lines(unsigned long paddr, int len)
++{
++ unsigned long sset, eset;
++
++ sset = (paddr & (nasys_dcache_size - 1)) & (~(nasys_dcache_line_size - 1));
++ eset = (((paddr & (nasys_dcache_size - 1)) + len) & (~(nasys_dcache_line_size - 1))) + nasys_dcache_line_size;
++
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushd 0(%0)\n\t"
++ "add %0,%0,%2\n\t"
++ "blt %0,%1,1b\n\t"
++ : : "r" (sset),"r" (eset), "r" (nasys_dcache_line_size));
++
++ sset = (paddr & (nasys_icache_size - 1)) & (~(nasys_icache_line_size - 1));
++ eset = (((paddr & (nasys_icache_size - 1)) + len) & (~(nasys_icache_line_size - 1))) + nasys_icache_line_size;
++
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushi %0\n\t"
++ "add %0,%0,%2\n\t"
++ "blt %0,%1,1b\n\t"
++ "flushp\n\t"
++ : : "r" (sset), "r" (eset), "r" (nasys_icache_line_size));
++
++}
++
++/*
++ * cache_push() semantics: Write back any dirty cache data in the given area,
++ * and invalidate the range in the instruction cache. It needs not (but may)
++ * invalidate those entries also in the data cache. The range is defined by a
++ * _physical_ address.
++ */
++
++void cache_push (unsigned long paddr, int len)
++{
++ cache_invalidate_lines(paddr, len);
++}
++
++
++/*
++ * cache_push_v() semantics: Write back any dirty cache data in the given
++ * area, and invalidate those entries at least in the instruction cache. This
++ * is intended to be used after data has been written that can be executed as
++ * code later. The range is defined by a _user_mode_ _virtual_ address.
++ */
++
++void cache_push_v (unsigned long vaddr, int len)
++{
++ cache_invalidate_lines(vaddr, len);
++}
++
++/*
++ * cache_push_all() semantics: Invalidate instruction cache and write back
++ * dirty data cache & invalidate.
++ */
++void cache_push_all (void)
++{
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushd 0(%0)\n\t"
++ "sub %0,%0,%1\n\t"
++ "bgt %0,r0,1b\n\t"
++ : : "r" (nasys_dcache_size), "r" (nasys_dcache_line_size));
++
++ __asm__ __volatile__ (
++ "1:\n\t"
++ "flushi %0\n\t"
++ "sub %0,%0,%1\n\t"
++ "bgt %0,r0,1b\n\t"
++ "flushp\n\t"
++ : : "r" (nasys_icache_size), "r" (nasys_icache_line_size));
++
++}
++
++/*
++ * dcache_push() semantics: Write back and dirty data cache and invalidate
++ * the range.
++ */
++void dcache_push (unsigned long vaddr, int len)
++{
++ cache_invalidate_data(vaddr, len);
++}
++
++/*
++ * icache_push() semantics: Invalidate instruction cache in the range.
++ */
++void icache_push (unsigned long vaddr, int len)
++{
++ cache_invalidate_inst(vaddr, len);
++}
++
++/* Map some physical address range into the kernel address space. The
++ * code is copied and adapted from map_chunk().
++ */
++
++unsigned long kernel_map(unsigned long paddr, unsigned long size,
++ int nocacheflag, unsigned long *memavailp )
++{
++ return paddr;
++}
++
++
++int is_in_rom(unsigned long addr)
++{
++ /* Default case, not in ROM */
++ return(0);
++}
++
++int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
++ unsigned long address, int write_access)
++{
++ BUG();
++ return VM_FAULT_OOM;
++}
+diff --git a/arch/nios2nommu/scripts/PTF/PTFParser.pm b/arch/nios2nommu/scripts/PTF/PTFParser.pm
+new file mode 100644
+index 0000000..c243c7b
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/PTFParser.pm
+@@ -0,0 +1,873 @@
++####################################################################
++#
++# This file was generated using Parse::Yapp version 1.05.
++#
++# Don't edit this file, use source file instead.
++#
++# ANY CHANGE MADE HERE WILL BE LOST !
++#
++####################################################################
++package PTFParser;
++use vars qw ( @ISA );
++use strict;
++
++@ISA= qw ( Parse::Yapp::Driver );
++#Included Parse/Yapp/Driver.pm file----------------------------------------
++{
++#
++# Module Parse::Yapp::Driver
++#
++# This module is part of the Parse::Yapp package available on your
++# nearest CPAN
++#
++# Any use of this module in a standalone parser make the included
++# text under the same copyright as the Parse::Yapp module itself.
++#
++# This notice should remain unchanged.
++#
++# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
++# (see the pod text in Parse::Yapp module for use and distribution rights)
++#
++
++package Parse::Yapp::Driver;
++
++require 5.004;
++
++use strict;
++
++use vars qw ( $VERSION $COMPATIBLE $FILENAME );
++
++$VERSION = '1.05';
++$COMPATIBLE = '0.07';
++$FILENAME=__FILE__;
++
++use Carp;
++
++#Known parameters, all starting with YY (leading YY will be discarded)
++my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
++ YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '');
++#Mandatory parameters
++my(@params)=('LEX','RULES','STATES');
++
++sub new {
++ my($class)=shift;
++ my($errst,$nberr,$token,$value,$check,$dotpos);
++ my($self)={ ERROR => \&_Error,
++ ERRST => \$errst,
++ NBERR => \$nberr,
++ TOKEN => \$token,
++ VALUE => \$value,
++ DOTPOS => \$dotpos,
++ STACK => [],
++ DEBUG => 0,
++ CHECK => \$check };
++
++ _CheckParams( [], \%params, \@_, $self );
++
++ exists($$self{VERSION})
++ and $$self{VERSION} < $COMPATIBLE
++ and croak "Yapp driver version $VERSION ".
++ "incompatible with version $$self{VERSION}:\n".
++ "Please recompile parser module.";
++
++ ref($class)
++ and $class=ref($class);
++
++ bless($self,$class);
++}
++
++sub YYParse {
++ my($self)=shift;
++ my($retval);
++
++ _CheckParams( \@params, \%params, \@_, $self );
++
++ if($$self{DEBUG}) {
++ _DBLoad();
++ $retval = eval '$self->_DBParse()';#Do not create stab entry on compile
++ $@ and die $@;
++ }
++ else {
++ $retval = $self->_Parse();
++ }
++ $retval
++}
++
++sub YYData {
++ my($self)=shift;
++
++ exists($$self{USER})
++ or $$self{USER}={};
++
++ $$self{USER};
++
++}
++
++sub YYErrok {
++ my($self)=shift;
++
++ ${$$self{ERRST}}=0;
++ undef;
++}
++
++sub YYNberr {
++ my($self)=shift;
++
++ ${$$self{NBERR}};
++}
++
++sub YYRecovering {
++ my($self)=shift;
++
++ ${$$self{ERRST}} != 0;
++}
++
++sub YYAbort {
++ my($self)=shift;
++
++ ${$$self{CHECK}}='ABORT';
++ undef;
++}
++
++sub YYAccept {
++ my($self)=shift;
++
++ ${$$self{CHECK}}='ACCEPT';
++ undef;
++}
++
++sub YYError {
++ my($self)=shift;
++
++ ${$$self{CHECK}}='ERROR';
++ undef;
++}
++
++sub YYSemval {
++ my($self)=shift;
++ my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
++
++ $index < 0
++ and -$index <= @{$$self{STACK}}
++ and return $$self{STACK}[$index][1];
++
++ undef; #Invalid index
++}
++
++sub YYCurtok {
++ my($self)=shift;
++
++ @_
++ and ${$$self{TOKEN}}=$_[0];
++ ${$$self{TOKEN}};
++}
++
++sub YYCurval {
++ my($self)=shift;
++
++ @_
++ and ${$$self{VALUE}}=$_[0];
++ ${$$self{VALUE}};
++}
++
++sub YYExpect {
++ my($self)=shift;
++
++ keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}}
++}
++
++sub YYLexer {
++ my($self)=shift;
++
++ $$self{LEX};
++}
++
++
++#################
++# Private stuff #
++#################
++
++
++sub _CheckParams {
++ my($mandatory,$checklist,$inarray,$outhash)=@_;
++ my($prm,$value);
++ my($prmlst)={};
++
++ while(($prm,$value)=splice(@$inarray,0,2)) {
++ $prm=uc($prm);
++ exists($$checklist{$prm})
++ or croak("Unknow parameter '$prm'");
++ ref($value) eq $$checklist{$prm}
++ or croak("Invalid value for parameter '$prm'");
++ $prm=unpack('@2A*',$prm);
++ $$outhash{$prm}=$value;
++ }
++ for (@$mandatory) {
++ exists($$outhash{$_})
++ or croak("Missing mandatory parameter '".lc($_)."'");
++ }
++}
++
++sub _Error {
++ print "Parse error.\n";
++}
++
++sub _DBLoad {
++ {
++ no strict 'refs';
++
++ exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ?
++ and return;
++ }
++ my($fname)=__FILE__;
++ my(@drv);
++ open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname";
++ while(<DRV>) {
++ /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/
++ and do {
++ s/^#DBG>//;
++ push(@drv,$_);
++ }
++ }
++ close(DRV);
++
++ $drv[0]=~s/_P/_DBP/;
++ eval join('',@drv);
++}
++
++#Note that for loading debugging version of the driver,
++#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
++#So, DO NOT remove comment at end of sub !!!
++sub _Parse {
++ my($self)=shift;
++
++ my($rules,$states,$lex,$error)
++ = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' };
++ my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
++ = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
++
++#DBG> my($debug)=$$self{DEBUG};
++#DBG> my($dbgerror)=0;
++
++#DBG> my($ShowCurToken) = sub {
++#DBG> my($tok)='>';
++#DBG> for (split('',$$token)) {
++#DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
++#DBG> ? sprintf('<%02X>',ord($_))
++#DBG> : $_;
++#DBG> }
++#DBG> $tok.='<';
++#DBG> };
++
++ $$errstatus=0;
++ $$nberror=0;
++ ($$token,$$value)=(undef,undef);
++ @$stack=( [ 0, undef ] );
++ $$check='';
++
++ while(1) {
++ my($actions,$act,$stateno);
++
++ $stateno=$$stack[-1][0];
++ $actions=$$states[$stateno];
++
++#DBG> print STDERR ('-' x 40),"\n";
++#DBG> $debug & 0x2
++#DBG> and print STDERR "In state $stateno:\n";
++#DBG> $debug & 0x08
++#DBG> and print STDERR "Stack:[".
++#DBG> join(',',map { $$_[0] } @$stack).
++#DBG> "]\n";
++
++
++ if (exists($$actions{ACTIONS})) {
++
++ defined($$token)
++ or do {
++ ($$token,$$value)=&$lex($self);
++#DBG> $debug & 0x01
++#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n";
++ };
++
++ $act= exists($$actions{ACTIONS}{$$token})
++ ? $$actions{ACTIONS}{$$token}
++ : exists($$actions{DEFAULT})
++ ? $$actions{DEFAULT}
++ : undef;
++ }
++ else {
++ $act=$$actions{DEFAULT};
++#DBG> $debug & 0x01
++#DBG> and print STDERR "Don't need token.\n";
++ }
++
++ defined($act)
++ and do {
++
++ $act > 0
++ and do { #shift
++
++#DBG> $debug & 0x04
++#DBG> and print STDERR "Shift and go to state $act.\n";
++
++ $$errstatus
++ and do {
++ --$$errstatus;
++
++#DBG> $debug & 0x10
++#DBG> and $dbgerror
++#DBG> and $$errstatus == 0
++#DBG> and do {
++#DBG> print STDERR "**End of Error recovery.\n";
++#DBG> $dbgerror=0;
++#DBG> };
++ };
++
++
++ push(@$stack,[ $act, $$value ]);
++
++ $$token ne '' #Don't eat the eof
++ and $$token=$$value=undef;
++ next;
++ };
++
++ #reduce
++ my($lhs,$len,$code,@sempar,$semval);
++ ($lhs,$len,$code)=@{$$rules[-$act]};
++
++#DBG> $debug & 0x04
++#DBG> and $act
++#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): ";
++
++ $act
++ or $self->YYAccept();
++
++ $$dotpos=$len;
++
++ unpack('A1',$lhs) eq '@' #In line rule
++ and do {
++ $lhs =~ /^\@[0-9]+\-([0-9]+)$/
++ or die "In line rule name '$lhs' ill formed: ".
++ "report it as a BUG.\n";
++ $$dotpos = $1;
++ };
++
++ @sempar = $$dotpos
++ ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
++ : ();
++
++ $semval = $code ? &$code( $self, @sempar )
++ : @sempar ? $sempar[0] : undef;
++
++ splice(@$stack,-$len,$len);
++
++ $$check eq 'ACCEPT'
++ and do {
++
++#DBG> $debug & 0x04
++#DBG> and print STDERR "Accept.\n";
++
++ return($semval);
++ };
++
++ $$check eq 'ABORT'
++ and do {
++
++#DBG> $debug & 0x04
++#DBG> and print STDERR "Abort.\n";
++
++ return(undef);
++
++ };
++
++#DBG> $debug & 0x04
++#DBG> and print STDERR "Back to state $$stack[-1][0], then ";
++
++ $$check eq 'ERROR'
++ or do {
++#DBG> $debug & 0x04
++#DBG> and print STDERR
++#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
++
++#DBG> $debug & 0x10
++#DBG> and $dbgerror
++#DBG> and $$errstatus == 0
++#DBG> and do {
++#DBG> print STDERR "**End of Error recovery.\n";
++#DBG> $dbgerror=0;
++#DBG> };
++
++ push(@$stack,
++ [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]);
++ $$check='';
++ next;
++ };
++
++#DBG> $debug & 0x04
++#DBG> and print STDERR "Forced Error recovery.\n";
++
++ $$check='';
++
++ };
++
++ #Error
++ $$errstatus
++ or do {
++
++ $$errstatus = 1;
++ &$error($self);
++ $$errstatus # if 0, then YYErrok has been called
++ or next; # so continue parsing
++
++#DBG> $debug & 0x10
++#DBG> and do {
++#DBG> print STDERR "**Entering Error recovery.\n";
++#DBG> ++$dbgerror;
++#DBG> };
++
++ ++$$nberror;
++
++ };
++
++ $$errstatus == 3 #The next token is not valid: discard it
++ and do {
++ $$token eq '' # End of input: no hope
++ and do {
++#DBG> $debug & 0x10
++#DBG> and print STDERR "**At eof: aborting.\n";
++ return(undef);
++ };
++
++#DBG> $debug & 0x10
++#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n";
++
++ $$token=$$value=undef;
++ };
++
++ $$errstatus=3;
++
++ while( @$stack
++ and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
++ or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
++ or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
++
++#DBG> $debug & 0x10
++#DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
++
++ pop(@$stack);
++ }
++
++ @$stack
++ or do {
++
++#DBG> $debug & 0x10
++#DBG> and print STDERR "**No state left on stack: aborting.\n";
++
++ return(undef);
++ };
++
++ #shift the error token
++
++#DBG> $debug & 0x10
++#DBG> and print STDERR "**Shift \$error token and go to state ".
++#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
++#DBG> ".\n";
++
++ push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]);
++
++ }
++
++ #never reached
++ croak("Error in driver logic. Please, report it as a BUG");
++
++}#_Parse
++#DO NOT remove comment
++
++1;
++
++}
++#End of include--------------------------------------------------
++
++
++#line 1 "PTFParser.yp"
++#
++# Altera PTF file parser
++#
++# Copyright (c) 2004 Microtronix Datacom Ltd.
++#
++
++package PTFParser;
++
++use PTF::PTFSection;
++
++#global variables should go here.
++
++#my $line = 0; # for error messages
++#my @sectionStack = (); # used to keep track of ptf sections
++#my $root;
++
++my $fh;
++
++sub new {
++ my($class)=shift;
++ ref($class)
++ and $class=ref($class);
++
++ my($self)=$class->SUPER::new( yyversion => '1.05',
++ yystates =>
++[
++ {#State 0
++ ACTIONS => {
++ 'IDENTIFIER' => 1
++ },
++ GOTOS => {
++ 'section' => 2,
++ 'section_title' => 3
++ }
++ },
++ {#State 1
++ ACTIONS => {
++ 'IDENTIFIER' => 4,
++ 'STRING_LITERAL' => 6,
++ 'NUMBER' => 7
++ },
++ DEFAULT => -3,
++ GOTOS => {
++ 'section_name' => 5
++ }
++ },
++ {#State 2
++ ACTIONS => {
++ '' => 8
++ }
++ },
++ {#State 3
++ ACTIONS => {
++ "{" => 9
++ }
++ },
++ {#State 4
++ DEFAULT => -4
++ },
++ {#State 5
++ DEFAULT => -2
++ },
++ {#State 6
++ DEFAULT => -6
++ },
++ {#State 7
++ DEFAULT => -5
++ },
++ {#State 8
++ DEFAULT => 0
++ },
++ {#State 9
++ ACTIONS => {
++ 'IDENTIFIER' => 11,
++ 'HIERARCHICAL_NAME' => 13
++ },
++ DEFAULT => -7,
++ GOTOS => {
++ 'assignment_name' => 10,
++ 'assignment' => 12,
++ 'section_element' => 14,
++ 'section' => 15,
++ 'section_title' => 3
++ }
++ },
++ {#State 10
++ ACTIONS => {
++ "=" => 16
++ }
++ },
++ {#State 11
++ ACTIONS => {
++ 'IDENTIFIER' => 4,
++ 'STRING_LITERAL' => 6,
++ 'NUMBER' => 7,
++ "=" => -11
++ },
++ DEFAULT => -3,
++ GOTOS => {
++ 'section_name' => 5
++ }
++ },
++ {#State 12
++ ACTIONS => {
++ 'IDENTIFIER' => 11,
++ 'HIERARCHICAL_NAME' => 13
++ },
++ DEFAULT => -7,
++ GOTOS => {
++ 'assignment_name' => 10,
++ 'assignment' => 12,
++ 'section_element' => 17,
++ 'section' => 15,
++ 'section_title' => 3
++ }
++ },
++ {#State 13
++ DEFAULT => -12
++ },
++ {#State 14
++ ACTIONS => {
++ "}" => 18
++ }
++ },
++ {#State 15
++ ACTIONS => {
++ 'IDENTIFIER' => 11,
++ 'HIERARCHICAL_NAME' => 13
++ },
++ DEFAULT => -7,
++ GOTOS => {
++ 'assignment_name' => 10,
++ 'assignment' => 12,
++ 'section_element' => 19,
++ 'section' => 15,
++ 'section_title' => 3
++ }
++ },
++ {#State 16
++ ACTIONS => {
++ 'STRING_LITERAL' => 20,
++ 'NUMBER' => 22
++ },
++ GOTOS => {
++ 'assignment_value' => 21
++ }
++ },
++ {#State 17
++ DEFAULT => -8
++ },
++ {#State 18
++ DEFAULT => -1
++ },
++ {#State 19
++ DEFAULT => -9
++ },
++ {#State 20
++ DEFAULT => -13
++ },
++ {#State 21
++ ACTIONS => {
++ ";" => 23
++ }
++ },
++ {#State 22
++ DEFAULT => -14
++ },
++ {#State 23
++ DEFAULT => -10
++ }
++],
++ yyrules =>
++[
++ [#Rule 0
++ '$start', 2, undef
++ ],
++ [#Rule 1
++ 'section', 4,
++sub
++#line 20 "PTFParser.yp"
++{
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++ pop @{$sectionStack};
++ }
++ ],
++ [#Rule 2
++ 'section_title', 2,
++sub
++#line 26 "PTFParser.yp"
++{
++ my $section = PTFSection->new (type => $_[1], name => $_[2]);
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++
++ if (scalar(@{$sectionStack}) == 0) {
++ $_[0]->YYData->{root} = $section;
++ } else {
++ my $parent = $sectionStack->[$#{$sectionStack}];
++ $parent->addSection ($section);
++ }
++
++ push @{$sectionStack}, $section;
++ }
++ ],
++ [#Rule 3
++ 'section_name', 0, undef
++ ],
++ [#Rule 4
++ 'section_name', 1, undef
++ ],
++ [#Rule 5
++ 'section_name', 1, undef
++ ],
++ [#Rule 6
++ 'section_name', 1, undef
++ ],
++ [#Rule 7
++ 'section_element', 0, undef
++ ],
++ [#Rule 8
++ 'section_element', 2, undef
++ ],
++ [#Rule 9
++ 'section_element', 2, undef
++ ],
++ [#Rule 10
++ 'assignment', 4,
++sub
++#line 52 "PTFParser.yp"
++{
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++ my $parent= $sectionStack->[$#{$sectionStack}];
++ $parent->addAssignment ($_[1], $_[3]);
++ }
++ ],
++ [#Rule 11
++ 'assignment_name', 1, undef
++ ],
++ [#Rule 12
++ 'assignment_name', 1, undef
++ ],
++ [#Rule 13
++ 'assignment_value', 1, undef
++ ],
++ [#Rule 14
++ 'assignment_value', 1, undef
++ ]
++],
++ @_);
++ bless($self,$class);
++}
++
++#line 67 "PTFParser.yp"
++
++
++sub _Error {
++# TODO: update this error function to be more useful
++ exists $_[0]->YYData->{ERRMSG}
++ and do {
++ print $_[0]->YYData->{ERRMSG};
++ delete $_[0]->YYData->{ERRMSG};
++ return;
++ };
++ print "Syntax error on line $_[0]->YYData->{line}.\n";
++}
++
++sub _Lexer {
++ my($parser)=shift;
++
++ if (! $parser->YYData->{INPUT}) {
++ if ($parser->YYData->{INPUT} = <$fh>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ }
++
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++
++ while (1) {
++
++ # skip blank lines
++ if ($parser->YYData->{INPUT} =~ s/^[ \t\r\n]*$//) {
++ if ($parser->YYData->{INPUT} = <$fh>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # Skip comments
++ if ($parser->YYData->{INPUT} =~ s/^#.*//) {
++ if ($parser->YYData->{INPUT} = <$fh>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # Don't continue if the line length is 0;
++ if (length $parser->YYData->{INPUT} == 0) {
++ if ($parser->YYData->{INPUT} = <$fh>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # tokenize input
++ $parser->YYData->{INPUT} =~ s/^([a-zA-Z_][a-zA-Z_0-9\/]*)//
++ and return('IDENTIFIER',$1);
++ $parser->YYData->{INPUT} =~ s/^"([^"\\]*(\\.[^"\\]*)*)"//
++ and return('STRING_LITERAL',$1);
++ $parser->YYData->{INPUT} =~ s/^"([^"\\]*(\\.[^"\\]*)*)//
++ and do {
++ my $literal = $1;
++
++ do {
++ if ($parser->YYData->{INPUT} = <$fh>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++
++ $parser->YYData->{INPUT} =~ s/([^"\\]*(\\.[^"\\]*)*)"//
++ and do {
++ $literal .= $1;
++ return ('STRING_LITERAL', $literal);
++ };
++
++ $parser->YYData->{INPUT} =~ s/([^"\\]*(\\.[^"\\]*)*)//
++ and $literal .= $1;
++ } while (1);
++ };
++ $parser->YYData->{INPUT} =~ s/^([0-9]+)//
++ and return('NUMBER',$1);
++ $parser->YYData->{INPUT} =~ s/^([\$]{1,2}[a-zA-Z0-9 \/_]+)//
++ and return('HIERARCHICAL_NAME',$1);
++ $parser->YYData->{INPUT} =~ s/^(.)//
++ and return($1,$1);
++ }
++}
++
++sub readPTF {
++ my $self = shift;
++ my $filename = shift;
++
++ # store information for later use
++ $self->YYData->{line} = 0;
++ $self->YYData->{sectionStack} = [];
++ undef $self->YYData->{root};
++
++ if (-e $filename) {
++ open (PTFFILE, $filename);
++ $fh = \*PTFFILE;
++ } else {
++ $fh = \*STDIN;
++ }
++
++ $self->YYParse (
++ yylex => \&_Lexer,
++ yyerror => \&_Error,
++ );
++
++ if (-e $filename) {
++ close PTFFILE;
++ }
++
++ return $self->YYData->{root};
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/PTF/PTFParser.yp b/arch/nios2nommu/scripts/PTF/PTFParser.yp
+new file mode 100644
+index 0000000..e105e6a
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/PTFParser.yp
+@@ -0,0 +1,178 @@
++%{#
++# Altera PTF file parser
++#
++# Copyright (c) 2004 Microtronix Datacom Ltd.
++#
++
++package PTFParser;
++
++use PTF::PTFSection;
++
++%}
++
++%%
++section: section_title '{' section_element '}' {
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++ pop @{$sectionStack};
++ }
++;
++
++section_title: IDENTIFIER section_name {
++ my $section = PTFSection->new (type => $_[1], name => $_[2]);
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++
++ if (scalar(@{$sectionStack}) == 0) {
++ $_[0]->YYData->{root} = $section;
++ } else {
++ my $parent = $sectionStack->[$#{$sectionStack}];
++ $parent->addSection ($section);
++ }
++
++ push @{$sectionStack}, $section;
++ }
++;
++
++section_name: # empty string
++ | IDENTIFIER
++ | NUMBER
++ | STRING_LITERAL
++;
++
++section_element: # empty element
++ | assignment section_element
++ | section section_element
++;
++
++assignment: assignment_name '=' assignment_value ';' {
++ my $sectionStack = $_[0]->YYData->{sectionStack};
++ my $parent= $sectionStack->[$#{$sectionStack}];
++ $parent->addAssignment ($_[1], $_[3]);
++ }
++;
++
++assignment_name: IDENTIFIER
++ | HIERARCHICAL_NAME
++;
++
++assignment_value: STRING_LITERAL
++ | NUMBER
++;
++
++%%
++
++sub _Error {
++# TODO: update this error function to be more useful
++ exists $_[0]->YYData->{ERRMSG}
++ and do {
++ print $_[0]->YYData->{ERRMSG};
++ delete $_[0]->YYData->{ERRMSG};
++ return;
++ };
++ print "Syntax error on line $_[0]->YYData->{line}.\n";
++}
++
++sub _Lexer {
++ my($parser)=shift;
++
++ if (! $parser->YYData->{INPUT}) {
++ if ($parser->YYData->{INPUT} = <PTFFILE>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ }
++
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++
++ while (1) {
++
++ # skip blank lines
++ if ($parser->YYData->{INPUT} =~ s/^[ \t\r\n]*$//) {
++ if ($parser->YYData->{INPUT} = <PTFFILE>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # Skip comments
++ if ($parser->YYData->{INPUT} =~ s/^#.*//) {
++ if ($parser->YYData->{INPUT} = <PTFFILE>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # Don't continue if the line length is 0;
++ if (length $parser->YYData->{INPUT} == 0) {
++ if ($parser->YYData->{INPUT} = <PTFFILE>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++ $parser->YYData->{INPUT} and
++ $parser->YYData->{INPUT} =~ s/^\s*//;
++ next;
++ }
++
++ # tokenize input
++ $parser->YYData->{INPUT} =~ s/^([a-zA-Z_][a-zA-Z_0-9\/]*)//
++ and return('IDENTIFIER',$1);
++ $parser->YYData->{INPUT} =~ s/^"([^"\\]*(\\.[^"\\]*)*)"//
++ and return('STRING_LITERAL',$1);
++ $parser->YYData->{INPUT} =~ s/^"([^"\\]*(\\.[^"\\]*)*)//
++ and do {
++ my $literal = $1;
++
++ do {
++ if ($parser->YYData->{INPUT} = <PTFFILE>) {
++ $parser->YYData->{line} += 1;
++ } else {
++ return ('', undef);
++ }
++
++ $parser->YYData->{INPUT} =~ s/([^"\\]*(\\.[^"\\]*)*)"//
++ and do {
++ $literal .= $1;
++ return ('STRING_LITERAL', $literal);
++ };
++
++ $parser->YYData->{INPUT} =~ s/([^"\\]*(\\.[^"\\]*)*)//
++ and $literal .= $1;
++ } while (1);
++ };
++ $parser->YYData->{INPUT} =~ s/^([0-9]+)//
++ and return('NUMBER',$1);
++ $parser->YYData->{INPUT} =~ s/^([\$]{1,2}[a-zA-Z0-9 \/_]+)//
++ and return('HIERARCHICAL_NAME',$1);
++ $parser->YYData->{INPUT} =~ s/^(.)//
++ and return($1,$1);
++ }
++}
++
++sub readPTF {
++ my $self = shift;
++ my $filename = shift;
++
++ # store information for later use
++ $self->YYData->{line} = 0;
++ $self->YYData->{sectionStack} = [];
++ undef $self->YYData->{root};
++
++ open (PTFFILE, $filename) or return undef;
++ $self->YYParse (
++ yylex => \&_Lexer,
++ yyerror => \&_Error,
++ );
++ close PTFFILE;
++
++ return $self->YYData->{root};
++}
+diff --git a/arch/nios2nommu/scripts/PTF/PTFSection.pm b/arch/nios2nommu/scripts/PTF/PTFSection.pm
+new file mode 100644
+index 0000000..a88d340
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/PTFSection.pm
+@@ -0,0 +1,81 @@
++package PTFSection;
++
++use strict;
++
++# Fields:
++# type = type of PTF Section
++# name = name of PTF Section (can be blank)
++# sections = array of section references
++# assignments = hash of assignments
++
++sub new {
++ my $invocant = shift;
++ my $class = ref($invocant) || $invocant;
++ my $self = {
++ @_,
++ sections => [],
++ assignments => {},
++ };
++ bless ($self, $class);
++ return $self;
++}
++
++sub addSection {
++ my ($self, $section) = @_;
++ push @{$self->{sections}}, $section;
++}
++
++sub getSections {
++ my ($self, $type) = @_;
++
++ if (! $type) {
++ return @{$self->{sections}};
++ }
++
++ my @matchedSections;
++ foreach my $section (@{$self->{sections}}) {
++ if ($section->type eq $type) {
++ push @matchedSections, $section;
++ }
++ }
++
++ return @matchedSections;
++}
++
++sub getSection {
++ my ($self, $type, $name) = @_;
++
++ if (! $name) {
++ $name = "";
++ }
++
++ foreach my $section (@{$self->{sections}}) {
++ if ($section->type eq $type and $section->name eq $name) {
++ return $section;
++ }
++ }
++
++}
++
++sub addAssignment {
++ my ($self, $name, $value) = @_;
++ $self->{assignments}{$name} = $value;
++}
++
++sub getAssignment {
++ my ($self, $name) = @_;
++ return $self->{assignments}{$name};
++}
++
++sub type {
++ my $self = shift;
++ return $self->{type};
++}
++
++sub name {
++ my $self = shift;
++ return $self->{name};
++}
++
++
++1;
+diff --git a/arch/nios2nommu/scripts/PTF/SystemPTF.pm b/arch/nios2nommu/scripts/PTF/SystemPTF.pm
+new file mode 100644
+index 0000000..9f44cfe
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/SystemPTF.pm
+@@ -0,0 +1,149 @@
++package SystemPTF;
++
++use strict;
++
++use PTF::PTFParser;
++use PTF::PTFSection;
++use PTF::SystemPTF::CPU;
++use PTF::SystemPTF::Board;
++use PTF::SystemPTF::Module;
++
++# Fields:
++
++my %module_order;
++
++sub new {
++ my $invocant = shift;
++ my $class = ref($invocant) || $invocant;
++ my $self = {
++ filename => "",
++ @_,
++ };
++
++ my $parser = PTFParser->new;
++ $self->{root} = $parser->readPTF($self->{filename});
++
++ # if the specified PTF file could not be read properly, return undef;
++ $self->{root} or return;
++
++ # if the specified PTF file is not a SYSTEM, return undef.
++ if ($self->{root}->type ne 'SYSTEM') {
++ return;
++ }
++
++ # initialize the modulemap
++ my @modules = $self->{root}->getSections ("MODULE");
++ my $index = 0;
++ foreach my $module (@modules) {
++ # if the module is not enabled then do not add
++ my $SBI = $module->getSection ('SYSTEM_BUILDER_INFO', '');
++ if ($SBI->getAssignment ('Is_Enabled') eq "1") {
++ $self->{modules}->{$module->name} = $module;
++ $module_order{$module->name} = $index;
++ $index += 1;
++ }
++ }
++
++ bless ($self, $class);
++ return $self;
++}
++
++sub getName {
++ my ($self) = @_;
++ return $self->{root}->name;
++}
++
++sub getCPUList {
++ my ($self, @classes) = @_;
++ my @cpulist = ();
++
++ foreach my $module_name (keys (%{$self->{modules}})) {
++ my $module = $self->{modules}->{$module_name};
++ my $module_class = $module->getAssignment ('class');
++ foreach my $class (@classes) {
++ if ($module_class eq $class) {
++ push @cpulist, $module->name;
++ }
++ }
++ }
++
++ return @cpulist;
++}
++
++sub getCPU {
++ my ($self, $name) = @_;
++
++ my $cpu = CPU->new (ptf => $self->{modules}->{$name});
++}
++
++sub getModule {
++ my ($self, $name) = @_;
++
++ my $module = Module->new (ptf => $self->{modules}->{$name});
++}
++
++sub getSlaveModules {
++ my ($self, $master, $type) = @_;
++
++ # create %connected set with just the master
++ # value of hash key is inconsequential
++ my %connected;
++ $connected{$master} = ( );
++
++ # create %pool set with all modules
++ # value of hash key is inconsequential
++ my %pool;
++ @pool{keys (%{$self->{modules}})} = ( );
++
++ my $dirty = 1;
++ while ($dirty) {
++ # %pool = difference (%pool, %connected)
++ delete @pool{ keys %connected };
++
++ $dirty = 0;
++
++ foreach my $name (keys %pool) {
++ my $mod = $self->getModule ($name);
++ my %mod_masters;
++ @mod_masters{ $mod->getMasters ($type) } = ( );
++
++ # if intersection (%masters, %connected) is not empty
++ delete @mod_masters{
++ grep ( ! exists $connected{ $_ },
++ keys %mod_masters) };
++
++ if (scalar(keys(%mod_masters)) > 0) {
++ $connected{$name} = ( );
++ $dirty = 1;
++ }
++ }
++ }
++
++ delete $connected{$master};
++
++ return sort module_comparison keys (%connected);
++}
++
++sub getClockFreq () {
++ my ($self) = @_;
++
++ my $wsa = $self->{root}->getSection ('WIZARD_SCRIPT_ARGUMENTS', '');
++ $wsa or return;
++
++ my $result = $wsa->getAssignment ('clock_freq');
++ return $result;
++}
++
++# This is not really a class method... more of a helper function really...
++sub module_comparison {
++ if ($module_order{$a} > $module_order{$b}) {
++ return 1;
++ } elsif ($module_order{$a} < $module_order{$b}) {
++ return -1;
++ } else {
++ return 0;
++ }
++}
++
++
++1;
+diff --git a/arch/nios2nommu/scripts/PTF/SystemPTF/Board.pm b/arch/nios2nommu/scripts/PTF/SystemPTF/Board.pm
+new file mode 100644
+index 0000000..fe2bbc8
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/SystemPTF/Board.pm
+@@ -0,0 +1,2 @@
++1;
++
+diff --git a/arch/nios2nommu/scripts/PTF/SystemPTF/CPU.pm b/arch/nios2nommu/scripts/PTF/SystemPTF/CPU.pm
+new file mode 100644
+index 0000000..ea10598
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/SystemPTF/CPU.pm
+@@ -0,0 +1,89 @@
++package CPU;
++
++use PTF::PTFSection;
++
++sub new {
++ my $invocant = shift;
++ my $class = ref($invocant) || $invocant;
++ my $self = {
++ @_,
++ };
++
++ # if no ptf section was passed in, then return undef
++ $self->{ptf} or return;
++
++ bless ($self, $class);
++ return $self;
++}
++
++sub getClass {
++ my ($self) = @_;
++
++ return $self->{ptf}->getAssignment ('class');
++}
++
++sub getVersion {
++ my ($self) = @_;
++
++ return $self->{ptf}->getAssignment ('class_version');
++}
++
++sub getConstant {
++ my ($self, $name) = @_;
++
++ # get WSA
++ $wsa = $self->{ptf}->getSection('WIZARD_SCRIPT_ARGUMENTS', '');
++ $wsa or return;
++
++ # get constants section
++ $constants = $wsa->getSection('CONSTANTS', '');
++ $constants or return;
++
++ # get section for specific constant
++ $constant = $constants->getSection ('CONSTANT', $name);
++ $constant or return;
++
++ # get value of constant
++ $value = $constant->getAssignment ('value');
++ return $value;
++}
++
++sub getWSAAssignment {
++ my ($self, $name) = @_;
++
++ # get WSA
++ $wsa = $self->{ptf}->getSection('WIZARD_SCRIPT_ARGUMENTS', '');
++ $wsa or return;
++
++ # get value of WSA Assignment
++ $value = $wsa->getAssignment ($name);
++ return $value;
++}
++
++sub getResetLocationOffset {
++ my ($self) = @_;
++
++ $wsa = $self->{ptf}->getSection('WIZARD_SCRIPT_ARGUMENTS', '');
++ $wsa or return;
++
++ my $location = $wsa->getAssignment ('reset_slave');
++ my $offset = $wsa->getAssignment ('reset_offset');
++
++ return ($location, $offset);
++}
++
++sub isEnabled {
++ my ($self) = @_;
++
++ $sbi = $self->{ptf}->getSection('SYSTEM_BUILDER_INFO', '');
++ $sbi or return;
++
++ my $enabled = $sbi->getAssignment ('Is_Enabled');
++ if ($enabled eq "1") {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/PTF/SystemPTF/Module.pm b/arch/nios2nommu/scripts/PTF/SystemPTF/Module.pm
+new file mode 100644
+index 0000000..48d246b
+--- /dev/null
++++ b/arch/nios2nommu/scripts/PTF/SystemPTF/Module.pm
+@@ -0,0 +1,267 @@
++package Module;
++
++use PTF::PTFSection;
++
++sub new {
++ my $invocant = shift;
++ my $class = ref($invocant) || $invocant;
++ my $self = {
++ @_,
++ };
++
++ # if no ptf section was passed in, then return undef
++ $self->{ptf} or return;
++
++ bless ($self, $class);
++ return $self;
++}
++
++sub getClass {
++ my ($self) = @_;
++
++ return $self->{ptf}->getAssignment ('class');
++}
++
++sub getPorts {
++ my ($self) = @_;
++
++ my @port_names;
++
++ my @ports = $self->{ptf}->getSections ('SLAVE');
++ foreach $port (@ports) {
++ push @port_names, $port->name;
++ }
++
++ return @port_names;
++}
++
++sub getPort {
++ my ($self, $port_name) = @_;
++
++ my $port;
++
++ if (! $port_name) {
++ # use first port found
++ my @port_names = $self->getPorts ();
++ $port = $self->{ptf}->getSection ('SLAVE', $port_names[0]);
++ } else {
++ $port = $self->{ptf}->getSection ('SLAVE', $port_name);
++ if (! $port) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++ }
++
++ return $port;
++}
++
++sub getWSAAssignment {
++ my ($self, $assignment) = @_;
++
++ my $WSA = $self->{ptf}->getSection ('WIZARD_SCRIPT_ARGUMENTS', '');
++ if (! $WSA) {
++ # return undef if the WSA section doesn't exist.
++ return;
++ }
++
++ my $result = $WSA->getAssignment ($assignment);
++
++ return $result;
++
++}
++
++sub getWSAConstant {
++ my ($self, $name) = @_;
++
++ my $WSA = $self->{ptf}->getSection ('WIZARD_SCRIPT_ARGUMENTS', '');
++ if (! $WSA) {
++ # return undef if the WSA section doesn't exist.
++ return;
++ }
++
++ my $constants = $WSA->getSection ('CONSTANTS', '');
++ if (! $constants) {
++ # return undef if the CONSTANTS section doesn't exist.
++ return;
++ }
++
++ my $constant = $constants->getSection ('CONSTANT', $name);
++ if (! $constant) {
++ # return undef if the CONSTANT $name section doesn't exist.
++ return;
++ }
++
++ my $result = $constant->getAssignment ('value');
++ return $result;
++
++}
++
++sub isMemoryDevice {
++ my ($self, $port_name) = @_;
++
++ my $port = $self->getPort ($port_name);
++ if (! $port) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $SBI = $port->getSection('SYSTEM_BUILDER_INFO', '');
++ if (! $SBI) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $result = $SBI->getAssignment('Is_Memory_Device');
++
++ return $result;
++}
++
++sub isCustomInstruction {
++ my ($self, $port_name) = @_;
++
++ my $port = $self->getPort ($port_name);
++ if (! $port) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $SBI = $port->getSection('SYSTEM_BUILDER_INFO', '');
++ if (! $SBI) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $result = $SBI->getAssignment('Is_Custom_Instruction');
++
++ return $result;
++}
++
++sub getBaseAddress {
++ my ($self, $port_name) = @_;
++
++ my $port = $self->getPort ($port_name);
++ if (! $port) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $SBI = $port->getSection('SYSTEM_BUILDER_INFO', '');
++ if (! $SBI) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $result = $SBI->getAssignment('Base_Address');
++ if ($result eq 'N/A') {
++ return;
++ }
++ return $result;
++}
++
++sub getSize {
++ my ($self, $port_name) = @_;
++
++ my $port = $self->getPort ($port_name);
++ $port or return; #return undef if the ptf section doesn't exist
++
++ my $SBI = $port->getSection ('SYSTEM_BUILDER_INFO', '');
++ my $data_width = $SBI->getAssignment ('Data_Width');
++ my $addr_width = $SBI->getAssignment ('Address_Width');
++
++ if ($data_width == 8) {
++ $size = 1 << $addr_width;
++ } elsif ($data_width == 16) {
++ $size = 1 << ($addr_width + 1);
++ } elsif ($data_width == 32) {
++ $size = 1 << ($addr_width + 2);
++ } elsif ($data_width == 64) {
++ $size = 1 << ($addr_width + 3);
++ } elsif ($data_width == 128) {
++ $size = 1 << ($addr_width + 4);
++ } else {
++ return;
++ }
++
++ $size_text = sprintf ("%#010x", $size);
++ return $size_text;
++}
++
++sub getIRQ {
++ my ($self, $port_name) = @_;
++
++ my $port = $self->getPort ($port_name);
++ if (! $port) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $SBI = $port->getSection('SYSTEM_BUILDER_INFO', '');
++ if (! $SBI) {
++ # return undef if the PTF section doesn't exist
++ return;
++ }
++
++ my $result = $SBI->getAssignment('Has_IRQ');
++ if ($result ne "1") {
++ # this device has no associated IRQ
++ return;
++ }
++
++ my @irq_masters = $SBI->getSections('IRQ_MASTER');
++ return $irq_masters[0]->getAssignment('IRQ_Number');
++}
++
++sub getMasters {
++ my ($self, $type) = @_;
++ my %masters = ();
++
++ # get list of all slave for device
++ my @slaves = $self->{ptf}->getSections ('SLAVE');
++
++ # get list of masters of relevant type for all slaves
++ foreach my $slave (@slaves) {
++ # get SBI for slave
++ my $SBI = $slave->getSection ('SYSTEM_BUILDER_INFO', '');
++
++ # get list of all MASTERED_BY and IRQ_MASTER sections
++ my @mastered_bys = $SBI->getSections ('MASTERED_BY');
++ my @irq_masters = $SBI->getSections ('IRQ_MASTER');
++
++ # start adding masters to the list
++ foreach my $master (@mastered_bys, @irq_masters) {
++ my $section_name = $master->name;
++ $section_name =~ /(.*)\/(.*)/;
++ my $master_name = $1;
++ my $master_type = $2;
++
++ if (! $type) {
++ $masters{$master_name} = ();
++ } else {
++ if ($master_type eq $type) {
++ $masters{$master_name} = ();
++ }
++ }
++
++ }
++
++ }
++
++ return keys (%masters);
++}
++
++sub isEnabled {
++ my ($self) = @_;
++
++ $sbi = $self->{ptf}->getSection('SYSTEM_BUILDER_INFO', '');
++ $sbi or return;
++
++ my $enabled = $sbi->getAssignment ('Is_Enabled');
++ if ($enabled eq "1") {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++1;
++
+diff --git a/arch/nios2nommu/scripts/gen_nios2_system.h.pl b/arch/nios2nommu/scripts/gen_nios2_system.h.pl
+new file mode 100644
+index 0000000..b7bcff5
+--- /dev/null
++++ b/arch/nios2nommu/scripts/gen_nios2_system.h.pl
+@@ -0,0 +1,314 @@
++# This script generates an appropriate hardware.h file for Nios II Linux based
++# on information within the target hardware's system.ptf file. This script
++# outputs everything to stdout.
++#
++# usage:
++#
++# [SOPC Builder]$ perl gen_hardware.h.pl <target cpu> <exec location> \
++# <upload location>
++#
++
++use PTF::SystemPTF;
++use strict;
++use integer;
++
++my $target_cpu;
++my $exec_location;
++my $upload_location;
++
++if (scalar (@ARGV) != 3) {
++ print STDERR "ERROR: Invalid number of parameters.\n";
++ print ("#error Invalid number of parameters.\n");
++ exit;
++} else {
++ $target_cpu = $ARGV[0];
++ $exec_location = $ARGV[1];
++ $upload_location = $ARGV[2];
++}
++
++#
++# startup the parser.
++#
++my $system = SystemPTF->new;
++if (!$system) {
++ print STDERR "ERROR: Specified file is not a SYSTEM ptf file.\n";
++ print ("#error Specified file is not a SYSTEM ptf file.\n");
++ exit;
++}
++
++#
++# print header for nios2_system.h
++#
++print <<ENDOFHEADER;
++#ifndef __NIOS2_SYSTEM_H__
++#define __NIOS2_SYSTEM_H__
++
++/*
++ * This file contains hardware information about the target platform.
++ * The nios2_system.h file is being phased out and will be removed in a
++ * later release.
++ *
++ * All base addresses for non memory devices have their high bit turned on to
++ * bypass the cache.
++ *
++ * This file is automatically generated. Do not modify.
++ */
++
++ENDOFHEADER
++
++#
++# generate contents for nios2_system.h
++#
++my $result; # dummy variable
++my $cpu = $system->getCPU ($target_cpu);
++if (! $cpu) {
++ print STDERR "ERROR: $target_cpu is not a valid CPU in system: " . $system->getName () . ".\n";
++ print "#error $target_cpu is not a valid CPU in system: " . $system->getName () . ".\n";
++ exit 1;
++}
++
++my $exec_module = $system->getModule ($exec_location);
++if (! $exec_module) {
++ print STDERR "ERROR: $exec_location is not a valid module in the system: " . $system->getName() . ".\n";
++ print "#error $exec_location is not a valid module in system: " . $system->getName () . ".\n";
++ exit 1;
++}
++
++my $upload_module = $system->getModule ($upload_location);
++if (! $upload_module) {
++ print STDERR "ERROR: $upload_location is not a valid module in the system: " . $system->getName() . ".\n";
++ print "#error $upload_location is not a valid module in system: " . $system->getName () . ".\n";
++ exit 1;
++}
++
++my %found_classes;
++my @found_classes_order;
++
++# the SYSPTF environment variable is set by kernel build process.
++if ($ENV{SYSPTF} ne "") {
++ print "/* Input System: " . $ENV{SYSPTF} . ":" . $system->getName () . " */\n";
++} else {
++ print "/* Input System: " . $system->getName () . " */\n";
++}
++print "/* Target CPU: " . $target_cpu . " */\n";
++
++print "\n";
++
++print <<ENDOFCONSTANTS;
++/* Nios II Constants */
++#define NIOS2_STATUS_PIE_MSK 0x1
++#define NIOS2_STATUS_PIE_OFST 0
++#define NIOS2_STATUS_U_MSK 0x2
++#define NIOS2_STATUS_U_OFST 1
++ENDOFCONSTANTS
++
++print "\n";
++
++print "/*\n";
++print " * Outputting basic values from system.ptf.\n";
++print " */\n\n";
++
++#
++# Start outputing information about each module.
++#
++my @module_names = $system->getSlaveModules ($target_cpu);
++foreach my $module_name (@module_names) {
++ my $module = $system->getModule ($module_name);
++ my $module_class = $module->getClass ();
++ my @module_ports = $module->getPorts ();
++ my $mask = 0;
++ my $text_printed = 0;
++ my $output = "";
++
++ # $output .= "/* $module_name (of type $module_class) */\n";
++
++ if (! exists $found_classes{$module_class}) {
++ push @found_classes_order, $module_class;
++ }
++ push @{$found_classes{$module_class}}, $module_name;
++
++ if (! $module->isMemoryDevice () && ! $module->isCustomInstruction ()) {
++ # turn on high bit for base address
++ $mask = 0x80000000;
++ }
++
++ if (scalar (@module_ports) == 1) {
++ my $base_address;
++ my $mem_size;
++ my $mem_end;
++
++ # base address information
++ $base_address = $module->getBaseAddress ();
++ if ($base_address) {
++ $output .= sprintf ("#define na_%-50s %#010x\n",
++ ($module_name, hex ($base_address) | $mask));
++ $text_printed = 1;
++ }
++ if ($module->isMemoryDevice()) {
++ # output size and end address
++ $mem_size = $module->getSize();
++ $output .= sprintf ("#define na_%-50s %#010x\n",
++ ($module_name . "_size", hex ($mem_size)));
++ $mem_end = hex ($mem_size) + hex($base_address);
++ $output .= sprintf ("#define na_%-50s %#010x\n",
++ ($module_name . "_end", $mem_end));
++
++ $text_printed = 1;
++ }
++
++ # irq information
++ $result = $module->getIRQ ();
++ if (defined ($result)) {
++ $output .= sprintf ("#define na_%-30s %30s\n",
++ ($module_name . "_irq", $result));
++ $text_printed = 1;
++ }
++
++ } else {
++ # if device has multiple ports
++ foreach my $port_name (@module_ports) {
++ # base address information
++ $result = $module->getBaseAddress ($port_name);
++ if ($result) {
++ $output .= sprintf ("#define na_%-50s %#010x\n",
++ ($module_name . "_" . $port_name, hex ($result) | $mask));
++ $text_printed = 1;
++ }
++
++ # irq information
++ $result = $module->getIRQ ($port_name);
++ if (defined ($result)) {
++ $output .= sprintf ("#define na_%-30s %30s\n",
++ ($module_name . "_" . $port_name . "_irq", $result));
++ $text_printed = 1;
++ }
++ }
++ }
++
++ if ($text_printed == 1) {
++ # $output .= "\n";
++ print $output;
++ }
++}
++
++print "\n";
++
++#
++# Handle special cases through customized perl scripts
++#
++foreach my $class_name (@found_classes_order) {
++ my $code = "";
++
++ foreach my $dir (@INC) {
++ if (-e "$dir/nios2_system.h/$class_name.pm") {
++ print "/* Executing ...scripts/nios2_system.h/$class_name.pm */\n";
++ $code .= "require \"$dir/nios2_system.h/BasicModule.pm\";";
++ $code .= "require \"$dir/nios2_system.h/$class_name.pm\";";
++ $code .= $class_name . "::run(\$system, \@{\$found_classes{\$class_name}});";
++ eval $code;
++ if ($@) {
++ print "#warning Could not execute ...scripts/nios2_system.h/$class_name.pm\n";
++ print "#warning Error message is stored in nios2_system.h:\n";
++ print "/*\n";
++ print "$@";
++ print "*/\n";
++ print STDERR "Could not execute ...scripts/nios2_system.h/$class_name.pm\n";
++ print STDERR "Error message follows:\n";
++ print STDERR "$@";
++ }
++ last;
++ }
++ }
++}
++
++#
++# Write out system information
++#
++print "/*\n";
++print " * Basic System Information\n";
++print " */\n";
++
++$result = $cpu->getWSAAssignment ('cache_icache_size');
++printf ("#define %-53s %10d\n", ("nasys_icache_size", $result));
++
++$result = $cpu->getConstant ('nasys_icache_line_size');
++printf ("#define %-53s %10d\n", ("nasys_icache_line_size", $result));
++
++$result = $cpu->getWSAAssignment ('cache_dcache_size');
++printf ("#define %-53s %10d\n", ("nasys_dcache_size", $result));
++
++$result = $cpu->getConstant ('nasys_dcache_line_size');
++printf ("#define %-53s %10d\n", ("nasys_dcache_line_size", $result));
++
++print "\n";
++
++printf ("#define %-33s %30s\n",
++ ("nasys_program_mem", "na_${exec_location}"));
++printf ("#define %-33s %30s\n",
++ ("nasys_program_mem_size", "na_${exec_location}_size"));
++printf ("#define %-33s %30s\n",
++ ("nasys_program_mem_end", "na_${exec_location}_end"));
++
++print "\n";
++
++if ($upload_location eq "flash_kernel") {
++ # nothing to do
++ print ("/* Redefinition of CFI flash memory unecessary */\n");
++} else {
++ my $module = $system->getModule ("flash_kernel");
++ if ($module) {
++ # there is a conflicting module in the system, error.
++ print STDERR "Error, a SOPC module named flash_kernel already exists but is not the upload location.\n";
++ print "#error The module name \"flash_kernel\" already exists but isn't the upload location.\n";
++ print "#error This will break the kernel.\n";
++ print "#error Please rename the module to something else in SOPC Builder.\n\n";
++ exit 1;
++ } else {
++ print ("/*\n");
++ print (" * Redefining upload location ($upload_location) to flash_kernel.\n");
++ print (" */\n\n");
++ # undefine the original module names and re-define them here.
++ print ("#undef na_${upload_location}\n");
++ print ("#undef na_${upload_location}_size\n");
++ print ("#undef na_${upload_location}_end\n");
++
++ my $base_address = $upload_module->getBaseAddress ();
++ printf ("#define %-33s %30s\n",
++ ("na_flash_kernel", $base_address));
++
++ my $mem_size = $upload_module->getSize();
++ printf ("#define %-33s %30s\n",
++ ("na_flash_kernel_size", $mem_size));
++
++ my $mem_end = hex ($base_address) + hex ($mem_size);
++ printf ("#define %-53s %#010x\n",
++ ("na_flash_kernel_end", $mem_end));
++ }
++}
++
++print "\n";
++
++printf ("#define %-33s %30s\n",
++ ("nasys_clock_freq", $system->getClockFreq()));
++printf ("#define %-33s %30s\n",
++ ("nasys_clock_freq_1000", int ($system->getClockFreq()) / 1000));
++
++{
++ my ($reset_location, $reset_offset) = $cpu->getResetLocationOffset();
++ my ($reset_module_name, $reset_port_name) = ($reset_location =~ /(.*)\/(.*)/);
++ my $reset_module = $system->getModule ($reset_module_name);
++ my $reset_address = $reset_module->getBaseAddress ($reset_port_name);
++
++ $reset_address = hex ($reset_address) + hex ($reset_offset);
++ printf ("#define %-53s %#010x\n",
++ ("CPU_RESET_ADDRESS", $reset_address));
++}
++
++print "\n";
++
++#
++# print footer for nios2_system.h
++#
++print <<ENDOFFOOTER;
++#endif /* __NIOS2_SYSTEM_H__ */
++ENDOFFOOTER
+diff --git a/arch/nios2nommu/scripts/hwselect.pl b/arch/nios2nommu/scripts/hwselect.pl
+new file mode 100644
+index 0000000..8181bee
+--- /dev/null
++++ b/arch/nios2nommu/scripts/hwselect.pl
+@@ -0,0 +1,166 @@
++# This script generates arch/nios2nommu/hardware.mk based on user input
++
++# usage:
++#
++# [SOPC Builder]$ perl hwselect.pl <ptf file path> <target file path>
++#
++
++use PTF::SystemPTF;
++use strict;
++use integer;
++
++my $ptf_filename;
++my $target_filename;
++my $index;
++my $system;
++
++#
++# Subroutine: Prompt user for an answer
++#
++
++sub request_answer {
++ my ($min, $max) = @_;
++ my $answer;
++
++ do {
++ print "Selection: ";
++ $answer = <STDIN>;
++ if (! ($answer >= $min && $answer <= $max)) {
++ print "Invalid response, please try again.\n";
++ }
++ } until $answer >= $min && $answer <= $max;
++
++ return $answer;
++}
++
++#
++# Check for correct number of args
++#
++
++if (scalar (@ARGV) != 2) {
++ print STDERR "ERROR: Invalid number of parameters.\n";
++ exit;
++} else {
++ $ptf_filename = $ARGV[0];
++ $target_filename = $ARGV[1];
++}
++
++#
++# Check to see if the specified file exists
++#
++
++if (! -e $ptf_filename) {
++ print STDERR "ERROR: Could not open SYSTEM ptf file.\n";
++ exit;
++}
++
++#
++# startup the parser.
++#
++$system = SystemPTF->new (filename => $ptf_filename);
++if (!$system) {
++ print STDERR "ERROR: Specified file is not a SYSTEM ptf file.\n";
++ exit;
++}
++
++#
++# Grab listing of Nios II processors and force user to select one:
++#
++
++print "\n--- Please select which CPU you wish to build the kernel against:\n\n";
++
++my @cpulist = $system->getCPUList ('altera_nios2');
++my %cpuinfo;
++
++$index = 1;
++foreach my $cpu (@cpulist) {
++ my $cpu_module = $system->getCPU ($cpu);
++ if ($cpu_module->isEnabled ()) {
++ my $class = $cpu_module->getClass();
++ my $type = $cpu_module->getWSAAssignment('cpu_selection');
++ my $version = $cpu_module->getVersion();
++
++ print "($index) $cpu - Class: $class Type: $type Version: $version\n";
++ }
++ $index += 1;
++}
++
++print "\n";
++
++my $cpu_selection = $cpulist[request_answer (1, $index - 1) - 1];
++
++#
++# Grab list of memory devices that $cpu_selection is hooked up to:
++#
++my @modulelist = $system->getSlaveModules ($cpu_selection);
++my %cfiinfo;
++my %meminfo;
++foreach my $module_name (@modulelist) {
++ my $module = $system->getModule ($module_name);
++ my $class = $module->getClass ();
++
++ if ($module->isEnabled ()) {
++ if ($class eq 'altera_avalon_cfi_flash') {
++ $cfiinfo{$module_name}{class} = $class;
++ $cfiinfo{$module_name}{size} = $module->getSize();
++ }
++
++ if ($module->isMemoryDevice()) {
++ $meminfo{$module_name}{class} = $class;
++ $meminfo{$module_name}{size} = $module->getSize();
++ }
++ }
++}
++
++#
++# Select an upload device:
++#
++print "\n--- Please select a device to upload the kernel to:\n\n";
++
++$index = 1;
++foreach my $name (keys (%cfiinfo)) {
++ my $size = hex ($cfiinfo{$name}{size});
++ print "($index) $name\n\tClass: $cfiinfo{$name}{class}\n\tSize: $size bytes\n\n";
++ $index += 1;
++}
++
++my @cfilist = keys (%cfiinfo);
++my $cfi_selected = $cfilist[request_answer (1, $index - 1) - 1];
++
++delete $meminfo{$cfi_selected};
++
++#
++# Select program memory to execute kernel from:
++#
++print "\n--- Please select a device to execute kernel from:\n\n";
++
++$index = 1;
++foreach my $name (keys (%meminfo)) {
++ my $size = hex ($meminfo{$name}{size});
++ print "($index) $name\n\tClass: $meminfo{$name}{class}\n\tSize: $size bytes\n\n";
++ $index += 1;
++}
++
++my @memlist = keys (%meminfo);
++my $mem_selected = $memlist[request_answer (1, $index - 1) - 1];
++
++print "\n--- Summary using\n\n";
++print "PTF: $ptf_filename\n";
++print "CPU: $cpu_selection\n";
++print "Device to upload to: $cfi_selected\n";
++print "Program memory to execute from: $mem_selected\n";
++
++#
++# Write settings out to Makefile fragment
++#
++open (HWMK, ">$target_filename") ||
++ die "Could not write to $target_filename";
++
++print HWMK "SYSPTF = $ptf_filename\n";
++print HWMK "CPU = $cpu_selection\n";
++print HWMK "UPLMEM = $cfi_selected\n";
++print HWMK "EXEMEM = $mem_selected\n";
++
++close (HWMK);
++
++print "\n--- Settings written to $target_filename\n\n";
+\ No newline at end of file
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/BasicModule.pm b/arch/nios2nommu/scripts/nios2_system.h/BasicModule.pm
+new file mode 100644
+index 0000000..e15c26b
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/BasicModule.pm
+@@ -0,0 +1,267 @@
++package BasicModule;
++
++require PTF::SystemPTF;
++require PTF::SystemPTF::Module;
++use strict;
++
++# Description: Prints an error message to stdout. This should prefix each line
++# with "#error " so that it can be properly read by the C
++# pre-processor.
++# Args: $module_name: name of module that was is required by driver
++# $class_name: name of device class that module belongs to.
++sub print_error_name_used {
++ my ($class, $module_name, $class_name) = @_;
++
++ print "#error The kernel requires that the $class->required_class_name device be named as $module_name.\n";
++ print "#error The current hardware has $module_name defined as a(n) $class_name device.\n";
++ print "#error This will cause the kernel to fail.\n";
++ print "#error Please rename the current $module_name device to something else in SOPC Builder.\n";
++}
++
++# Description: This casts the base address to a specific data type
++# By default, it does not cast the base address to
++# anything.
++sub base_address_cast {
++ my ($class, $port_name) = @_;
++ return;
++}
++
++# Description: This sub-routine prints out a prefix that is shown only once
++# before any translations take place.
++sub print_prefix {
++ my ($class, $system) = @_;
++ printf ("\n");
++}
++
++# Description: Prints a set of lines to stdout that re-defines all symbols
++# related to $module_name to the symbols required by the driver.
++# Typically starts off with "#undefine ..." statements followed
++# by one or more "#define statements".
++# Args: $required_module_name: the module name that's expected by the kernel.
++# $module_name: the name of the module that was found in the PTF file.
++sub translate {
++ my ($class, $system, $required_module_name, $module_name) = @_;
++
++ # get the necessary info about the module
++ my $module = $system->getModule ($module_name);
++ my @port_names = $module->getPorts ();
++
++ my $boolean_base_address_cast = 0;
++ if (scalar (@port_names) > 1) {
++ foreach my $port_name (@port_names) {
++ my $cast = $class->base_address_cast ($port_name);
++ if (defined ($cast)) {
++ $boolean_base_address_cast = 1;
++ last;
++ }
++ }
++ } else {
++ my $cast = $class->base_address_cast;
++ if (defined ($cast)) {
++ $boolean_base_address_cast = 1;
++ }
++ }
++
++ if ($module_name eq $required_module_name &&
++ !$boolean_base_address_cast) {
++ printf ("/* No translation necessary for $module_name */\n\n");
++ return;
++ }
++
++ # undefine the original entries
++ print "/* Redefining $module_name -> $required_module_name */\n";
++ if (scalar (@port_names) == 1) {
++ my $irq = $module->getIRQ ();
++ print "#undef na_" . $module_name . "\n";
++ if (defined ($irq)) {
++ print "#undef na_" . $module_name . "_irq\n";
++ }
++ print "\n";
++ } else {
++ foreach my $port_name (@port_names) {
++ print "#undef na_" . $module_name . "_" .
++ $port_name . "\n";
++ my $irq = $module->getIRQ ($port_name);
++ if (defined ($irq)) {
++ print "#undef na_" . $module_name . "_" .
++ $port_name . "_irq\n";
++ }
++ print "\n";
++ }
++ }
++
++ if (scalar (@port_names) == 1) {
++ # set up a string to pass to printf that will output the correct
++ # #define base address statement.
++
++ # turn on the high bit for the base address to bypass cache.
++ my $base_address = $module->getBaseAddress ();
++ $base_address = hex ($base_address) | 0x80000000;
++
++ my $cast = $class->base_address_cast;
++ $class->print_define_line ($required_module_name,
++ undef, "addr", $cast, $base_address);
++
++ # print out an IRQ define statement if necessary
++ my $irq = $module->getIRQ ();
++ if (defined ($irq)) {
++ $class->print_define_line ($required_module_name,
++ undef, "irq", undef, $irq);
++ }
++ printf ("\n");
++ } else {
++ foreach my $port_name (@port_names) {
++ my $cast = $class->base_address_cast ($port_name);
++ my $base_address = $module->getBaseAddress ($port_name);
++ $base_address = hex ($base_address) | 0x80000000;
++ $class->print_define_line ($required_module_name,
++ $port_name, "addr", $cast, $base_address);
++
++ my $irq = $module->getIRQ ($port_name);
++ if (defined ($irq)) {
++ $class->print_define_line (
++ $required_module_name, $port_name,
++ "irq", undef, $irq);
++ }
++
++ print "\n";
++ }
++ }
++}
++
++# Description: The following sub-routine prints out "undef" or "define"
++# statements based on the arguments received.
++# Args: $name: "define" or "undef"
++# $port: name of port (if applicable)
++# $type: "addr" or "irq"
++# $cast: data type to cast base address to (if applicable)
++# $value: value of symbol to be defined (if applicable)
++sub print_define_line {
++ my ($class, $name, $port, $type, $cast, $value) = @_;
++
++ # construct the symbol that is being used
++ my $symbol .= "na_";
++ $symbol .= $name;
++
++ $symbol .= defined ($port) ? "_" . $port : "";
++ $symbol .= $type eq "irq" ? "_irq" : "";
++
++ my $string_value;
++ if ($type eq "addr") {
++ $string_value = sprintf ("%#010x", $value);
++ if (defined $cast) {
++ $string_value = "(($cast*) $string_value)";
++ }
++ } else {
++ $string_value = $value;
++ }
++ printf ("%-41s %30s\n", "#define $symbol", $string_value);
++}
++
++# Description: This sub-routine prints out a prefix that is shown only once
++# after any translations take place.
++sub print_suffix {
++ my ($class, $system) = @_;
++ # intentionally left empty
++}
++
++# Description: The following function allows the class to further determine if
++# the module is valid. For instance, the timer class requires
++# that the selected module does not have a fixed period.
++# This function returns true by default which basically means
++# that all modules belonging to class are valid.
++sub is_module_valid {
++ my ($class, $system, $module_name) = @_;
++ return 1;
++}
++
++# Description: This sub-routine is required. It is executed by the
++# "../gen_nios2_system_h.pl" script whenever any devices of type
++# $class->required_class_name are found in the PTF file.
++#
++# It looks for any conflicting module names first. If any are
++# found, "print_error_name_used" is called and this perl module
++# exits.
++#
++# It then goes through the list of module names found in the PTF
++# file that are of type $class->required_class_name and maps them to the
++# list of unused names in $class->required_module_names.
++#
++# Finally, it will call the "translate" sub-routine to output the
++# symbols required by the driver.
++# Args: $system: a variable containing a reference to the system.ptf file that
++# provides full access to any information in the file.
++# @found_module_names: a list of module names that are of type
++# $class->required_class_name
++sub run2 {
++ my ($class, $system, @found_module_names) = @_;
++
++ # initialize a mapping of required module names to actual module names
++ my %module_map;
++ foreach my $module_name ($class->required_module_names) {
++ $module_map{$module_name} = "";
++ }
++
++ # if the required module name is already in use in the PTF file for a
++ # different device class, flag it as an error.
++ my $error_found = 0;
++ foreach my $module_name ($class->required_module_names) {
++ my $module = $system->getModule ($module_name);
++
++ if (!defined ($module)) {
++ next;
++ }
++
++ my $class_name = $module->getClass ();
++ if ($class_name ne $class->required_class_name) {
++ $class->print_error_name_used ($class, $module_name, $class_name);
++ $error_found = 1;
++ }
++ }
++
++ # if errors were found, then there's no point in continuing.
++ if ($error_found == 1) {
++ return;
++ }
++
++ # Run through list of modules that belong to the class and start
++ # mapping each module name to the first unused required module name
++ # as defined above
++ FOUND_MOD_LOOP: foreach my $module_name (@found_module_names) {
++
++ # If the module name has already been used, then continue
++ # to the next one.
++ foreach my $required_module_name ($class->required_module_names) {
++ if ($module_map{$required_module_name} eq $module_name) {
++ next FOUND_MOD_LOOP;
++ }
++ }
++
++ # assertion: $module_name is not mapped yet.
++ foreach my $required_module_name ($class->required_module_names) {
++ if ($module_map{$required_module_name} ne "") {
++ next;
++ }
++
++ if ($class->is_module_valid ($system, $module_name)) {
++ $module_map{$required_module_name} = $module_name;
++ }
++ last;
++ }
++ }
++
++ $class->print_prefix ($system);
++
++ # Now that everything's been mapped (or as close as we're going to get
++ # to it being mapped), start printing out the literal translation.
++ foreach my $required_module_name ($class->required_module_names) {
++ my $module_name = $module_map{$required_module_name};
++ if (length ($module_name) > 0) {
++ $class->translate ($system, $required_module_name, $module_name);
++ }
++ }
++
++ $class->print_suffix ($system);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_cf.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_cf.pm
+new file mode 100644
+index 0000000..dada452
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_cf.pm
+@@ -0,0 +1,18 @@
++package altera_avalon_cf;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "ide"
++}
++
++sub required_class_name {
++ "altera_avalon_cf"
++}
++
++sub run {
++ altera_avalon_cf->run2(@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_jtag_uart.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_jtag_uart.pm
+new file mode 100644
+index 0000000..22bb9c9
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_jtag_uart.pm
+@@ -0,0 +1,18 @@
++package altera_avalon_jtag_uart;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ ("jtag_uart")
++}
++
++sub required_class_name {
++ "altera_avalon_jtag_uart";
++}
++
++sub run {
++ altera_avalon_jtag_uart->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_lan91c111.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_lan91c111.pm
+new file mode 100644
+index 0000000..5a29b7e
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_lan91c111.pm
+@@ -0,0 +1,38 @@
++package altera_avalon_lan91c111;
++
++require PTF::SystemPTF;
++require PTF::SystemPTF::Module;
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "enet"
++}
++
++sub required_class_name {
++ "altera_avalon_lan91c111"
++}
++
++sub translate {
++ my $class = shift;
++ my ($system, $required_module_name, $module_name) = @_;
++ $class->SUPER::translate (@_);
++
++ my $module = $system->getModule ($module_name);
++
++ my $offset_keyword = "LAN91C111_REGISTERS_OFFSET";
++ my $offset = $module->getWSAConstant ($offset_keyword);
++ printf ("%-41s %30s\n", "#define $offset_keyword", $offset);
++
++ my $width_keyword = "LAN91C111_DATA_BUS_WIDTH";
++ my $width = $module->getWSAConstant ($width_keyword);
++ printf ("%-41s %30s\n", "#define $width_keyword", $width);
++
++ print "\n";
++}
++
++sub run {
++ altera_avalon_lan91c111->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_pio.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_pio.pm
+new file mode 100644
+index 0000000..afdbcae
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_pio.pm
+@@ -0,0 +1,46 @@
++package altera_avalon_pio;
++
++require PTF::SystemPTF;
++require PTF::SystemPTF::Module;
++use strict;
++
++sub run {
++ my ($system, @pio_names) = @_;
++
++ print "#ifndef __ASSEMBLY__\n";
++ print "#include <asm/pio_struct.h>\n";
++ print "#endif\n\n";
++
++ foreach my $pio_name (@pio_names) {
++ my $module = $system->getModule ($pio_name);
++
++ # get all the relevant information
++ my $base_address = $module->getBaseAddress ();
++ $base_address = hex ($base_address) | 0x80000000;
++ my $irq = $module->getIRQ ();
++
++ print "/* Casting base addresses to the appropriate structure */\n";
++
++ # undefine all the old symbols first
++ print "#undef na_${pio_name}\n";
++ if (defined ($irq)) {
++ print "#undef na_${pio_name}_irq\n";
++ print "\n";
++ }
++
++ # define base address
++ $base_address = sprintf ("%#010x", $base_address);
++ printf ("%-41s %30s\n", "#define na_${pio_name}",
++ "((np_pio*) ${base_address})");
++
++ # define irq
++ if (defined ($irq)) {
++ printf ("%-41s %30s\n", "#define na_${pio_name}_irq",
++ $irq);
++ }
++
++ print "\n";
++ }
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_spi.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_spi.pm
+new file mode 100644
+index 0000000..719a22c
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_spi.pm
+@@ -0,0 +1,30 @@
++package altera_avalon_spi;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "spi"
++}
++
++sub required_class_name {
++ "altera_avalon_spi"
++}
++
++sub base_address_cast {
++ "np_spi"
++}
++
++sub print_prefix {
++ my ($class, $system) = @_;
++
++ print "#ifndef __ASSEMBLY__\n";
++ print "#include <asm/spi_struct.h>\n";
++ print "#endif\n\n";
++}
++
++sub run {
++ altera_avalon_spi->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_sysid.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_sysid.pm
+new file mode 100644
+index 0000000..deb9826
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_sysid.pm
+@@ -0,0 +1,18 @@
++package altera_avalon_sysid;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_class_name {
++ "altera_avalon_sysid"
++}
++
++sub required_module_names {
++ "sysid"
++}
++
++sub run {
++ altera_avalon_sysid->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_timer.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_timer.pm
+new file mode 100644
+index 0000000..495ccdc
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_timer.pm
+@@ -0,0 +1,46 @@
++package altera_avalon_timer;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_class_name {
++ "altera_avalon_timer";
++}
++
++sub required_module_names {
++ "timer0"
++}
++
++sub print_prefix {
++ my ($class, $system) = @_;
++
++ print "\n";
++ print "#ifndef __ASSEMBLY__\n";
++ print "#include <asm/timer_struct.h>\n";
++ print "#endif\n";
++ print "\n";
++}
++
++sub base_address_cast {
++ "np_timer"
++}
++
++# only timers with a non-fixed-period are valid
++sub is_module_valid {
++ my ($class, $system, $module_name) = @_;
++
++ my $module = $system->getModule ($module_name);
++ my $fixed_period = $module->getWSAAssignment ('fixed_period');
++
++ if ($fixed_period eq '0') {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++sub run {
++ altera_avalon_timer->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_uart.pm b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_uart.pm
+new file mode 100644
+index 0000000..abf48d7
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/altera_avalon_uart.pm
+@@ -0,0 +1,44 @@
++package altera_avalon_uart;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ ("uart0", "uart1", "uart2", "uart3")
++}
++
++sub required_class_name {
++ "altera_avalon_uart";
++}
++
++sub base_address_cast {
++ "np_uart"
++}
++
++sub print_prefix {
++ my ($class, $system) = @_;
++
++ print "#ifndef __ASSEMBLY__\n";
++ print "#include <asm/uart_struct.h>\n";
++ print "#endif\n\n";
++}
++
++sub translate {
++ my $class = shift;
++ my ($system, $required_module_name, $module_name) = @_;
++
++ $class->SUPER::translate (@_);
++
++ if (!defined ($altera_avalon_uart::default_uart)) {
++ print "/* The default uart is always the first one found in the PTF file */\n";
++ print "#define nasys_printf_uart na_$required_module_name\n\n";
++ $altera_avalon_uart::default_uart = $required_module_name;
++ }
++
++}
++
++sub run {
++ altera_avalon_uart->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/mtip_avalon_10_100_mac.pm b/arch/nios2nommu/scripts/nios2_system.h/mtip_avalon_10_100_mac.pm
+new file mode 100644
+index 0000000..fdd727b
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/mtip_avalon_10_100_mac.pm
+@@ -0,0 +1,18 @@
++package mtip_avalon_10_100_mac;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_class_name {
++ "mtip_avalon_10_100_mac";
++}
++
++sub required_module_names {
++ "mtip_mac"
++}
++
++sub run {
++ mtip_avalon_10_100_mac->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_dm9000.pm b/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_dm9000.pm
+new file mode 100644
+index 0000000..5985c2f
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_dm9000.pm
+@@ -0,0 +1,18 @@
++package mtx_avalon_dm9000;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "dm9000"
++}
++
++sub required_class_name {
++ "mtx_avalon_dm9000"
++}
++
++sub run {
++ mtx_avalon_dm9000->run2(@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_isp1161a1.pm b/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_isp1161a1.pm
+new file mode 100644
+index 0000000..e70ffa3
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/mtx_avalon_isp1161a1.pm
+@@ -0,0 +1,18 @@
++package mtx_avalon_isp1161a1;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "usb"
++}
++
++sub required_class_name {
++ "mtx_avalon_isp1161a1";
++}
++
++sub run {
++ mtx_avalon_isp1161a1->run2(@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/opencores_ethernet_mac.pm b/arch/nios2nommu/scripts/nios2_system.h/opencores_ethernet_mac.pm
+new file mode 100644
+index 0000000..7b580b5
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/opencores_ethernet_mac.pm
+@@ -0,0 +1,18 @@
++package opencores_ethernet_mac;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ "igor_mac"
++}
++
++sub required_class_name {
++ "opencores_ethernet_mac"
++}
++
++sub run {
++ opencores_ethernet_mac->run2 (@_);
++}
++
++1;
+diff --git a/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c.pm b/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c.pm
+new file mode 100644
+index 0000000..512d12c
+--- /dev/null
++++ b/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c.pm
+@@ -0,0 +1,18 @@
++package opencores_i2c;
++
++use base qw(BasicModule);
++use strict;
++
++sub required_module_names {
++ ("i2c_0", "i2c_1")
++}
++
++sub required_class_name {
++ "opencores_i2c";
++}
++
++sub run {
++ opencores_i2c->run2 (@_);
++}
++
++1;
+diff --git a/include/asm-nios2nommu/ChangeLog b/include/asm-nios2nommu/ChangeLog
+new file mode 100644
+index 0000000..94aaa27
+--- /dev/null
++++ b/include/asm-nios2nommu/ChangeLog
+@@ -0,0 +1,14 @@
++2004-06-29 Ken Hill <khill@microtronix.com>
++
++ * bitops.h (find_next_zero_bit): Fix problem with with masking for found_first
++ handling. The masking of the upper bits for size < 32 bits would set all
++ the bits to 1. Removing any zero's there may have been.
++
++2004-06-02 Ken Hill <khill@microtronix.com>
++
++ * processor.h (TASK_SIZE): Change na_sdram_end to nasys_program_mem_end to remove
++ dependancy on quartus memory component name.
++
++ * page.h (PAGE_OFFSET): Change na_sdram to nasys_program_mem to remove
++ dependancy on quartus memory component name.
++
+diff --git a/include/asm-nios2nommu/Kbuild b/include/asm-nios2nommu/Kbuild
+new file mode 100644
+index 0000000..abf0368
+--- /dev/null
++++ b/include/asm-nios2nommu/Kbuild
+@@ -0,0 +1,4 @@
++include include/asm-generic/Kbuild.asm
++
++header-y += traps.h
++header-y += io.h
+diff --git a/include/asm-nios2nommu/a.out.h b/include/asm-nios2nommu/a.out.h
+new file mode 100644
+index 0000000..8297687
+--- /dev/null
++++ b/include/asm-nios2nommu/a.out.h
+@@ -0,0 +1,85 @@
++/* $Id: a.out.h,v 1.1 2006/07/05 06:20:25 gerg Exp $ */
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_A_OUT_H__
++#define __NIOS2NOMMU_A_OUT_H__
++
++#define SPARC_PGSIZE 0x1000 /* Thanks to the sun4 architecture... */
++#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
++
++struct exec {
++ unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
++ unsigned char a_toolversion:7;
++ unsigned char a_machtype;
++ unsigned short a_info;
++ unsigned long a_text; /* length of text, in bytes */
++ unsigned long a_data; /* length of data, in bytes */
++ unsigned long a_bss; /* length of bss, in bytes */
++ unsigned long a_syms; /* length of symbol table, in bytes */
++ unsigned long a_entry; /* where program begins */
++ unsigned long a_trsize;
++ unsigned long a_drsize;
++};
++
++#define INIT_EXEC { \
++ .a_dynamic = 0, \
++ .a_toolversion = 0, \
++ .a_machtype = 0, \
++ .a_info = 0, \
++ .a_text = 0, \
++ .a_data = 0, \
++ .a_bss = 0, \
++ .a_syms = 0, \
++ .a_entry = 0, \
++ .a_trsize = 0, \
++ .a_drsize = 0, \
++}
++
++/* Where in the file does the text information begin? */
++#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
++
++/* Where do the Symbols start? */
++#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
++ (x).a_data + (x).a_trsize + \
++ (x).a_drsize)
++
++/* Where does text segment go in memory after being loaded? */
++#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \
++ ((x).a_entry < SPARC_PGSIZE)) ? \
++ 0 : SPARC_PGSIZE)
++
++/* And same for the data segment.. */
++#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
++ (N_TXTADDR(x) + (x).a_text) \
++ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
++
++#define N_TRSIZE(a) ((a).a_trsize)
++#define N_DRSIZE(a) ((a).a_drsize)
++#define N_SYMSIZE(a) ((a).a_syms)
++
++#ifdef __KERNEL__
++
++#define STACK_TOP TASK_SIZE
++
++#endif
++
++#endif /* __NIOS2NOMMU_A_OUT_H__ */
+diff --git a/include/asm-nios2nommu/altera_juart.h b/include/asm-nios2nommu/altera_juart.h
+new file mode 100644
+index 0000000..da6320d
+--- /dev/null
++++ b/include/asm-nios2nommu/altera_juart.h
+@@ -0,0 +1,36 @@
++/*------------------------------------------------------------------------
++ *
++ * linux/drivers/serial/altera_juart.h
++ *
++ * Driver for Altera JTAG UART core with Avalon interface
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * History:
++ * Jun/20/2005 DGT Microtronix Datacom NiosII
++ *
++ -----------------------------------------------------------------------*/
++
++#ifndef _ALTERA_JUART_H_
++ #define _ALTERA_JUART_H_
++
++ /* jtag uart details needed outside of the driver itself: */
++ /* by: arch/kernel/start.c - boot time error message(s) */
++
++ void jtaguart_console_write
++ ( struct console *co,
++ const char *s,
++ unsigned int count);
++
++#endif /* _ALTERA_JUART_H_ */
+diff --git a/include/asm-nios2nommu/asm-macros.h b/include/asm-nios2nommu/asm-macros.h
+new file mode 100644
+index 0000000..9dda7cd
+--- /dev/null
++++ b/include/asm-nios2nommu/asm-macros.h
+@@ -0,0 +1,331 @@
++/*
++ * Macro used to simplify coding multi-line assembler.
++ * Some of the bit test macro can simplify down to one line
++ * depending on the mask value.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++/*
++ * ANDs reg2 with mask and places the result in reg1.
++ *
++ * You cannnot use the same register for reg1 & reg2.
++ */
++
++.macro ANDI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ movhi \reg1,%hi(\mask)
++ movui \reg1,%lo(\mask)
++ and \reg1,\reg1,\reg2
++ .else
++ andi \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ andhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * ORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro ORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ orhi \reg1,\reg2,%hi(\mask)
++ ori \reg1,\reg2,%lo(\mask)
++ .else
++ ori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ orhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * XORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro XORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ xorhi \reg1,\reg2,%hi(\mask)
++ xori \reg1,\reg1,%lo(\mask)
++ .else
++ xori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ xorhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * This is a support macro for BTBZ & BTBNZ. It checks
++ * the bit to make sure it is valid 32 value.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BT reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is non-zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBNZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTC reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ xori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ xorhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTS reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ ori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ orhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTR reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ andi \reg2,\reg2,%lo(~(1 << \bit))
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ andhi \reg2,\reg2,%lo(~(1 << (\bit - 16)))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBNZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBNZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBNZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the all the bits in the mask are zero it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the any of the bits in the mask are 1 it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBNZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Pushes reg onto the stack.
++ */
++
++.macro PUSH reg
++ addi sp,sp,-4
++ stw \reg,0(sp)
++.endm
++
++/*
++ * Pops the top of the stack into reg.
++ */
++
++.macro POP reg
++ ldw \reg,0(sp)
++ addi sp,sp,4
++.endm
++
++/*
++ * Clears reg
++ */
++
++.macro CLR reg
++ mov \reg,r0
++.endm
++
++/*
++ * The preprocessor macro does not work for
++ * the nios2 compiler. Undefine ENTRY and define
++ * a real assembler macro.
++ */
++#undef ENTRY
++#define ENTRY(name) ASM_ENTRY name
++
++.macro ASM_ENTRY name
++.globl \name
++__ALIGN
++ \name:
++.endm
+diff --git a/include/asm-nios2nommu/atomic.h b/include/asm-nios2nommu/atomic.h
+new file mode 100644
+index 0000000..fb627de
+--- /dev/null
++++ b/include/asm-nios2nommu/atomic.h
+@@ -0,0 +1,146 @@
++#ifndef __ASM_SH_ATOMIC_H
++#define __ASM_SH_ATOMIC_H
++
++/*
++ * Atomic operations that C can't guarantee us. Useful for
++ * resource counting etc..
++ *
++ */
++
++typedef struct { volatile int counter; } atomic_t;
++
++#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
++
++#define atomic_read(v) ((v)->counter)
++#define atomic_set(v,i) ((v)->counter = (i))
++
++#include <asm/system.h>
++
++/*
++ * To get proper branch prediction for the main line, we must branch
++ * forward to code at the end of this object's .text section, then
++ * branch back to restart the operation.
++ */
++
++static __inline__ void atomic_add(int i, atomic_t * v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ *(long *)v += i;
++ local_irq_restore(flags);
++}
++
++static __inline__ void atomic_sub(int i, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ *(long *)v -= i;
++ local_irq_restore(flags);
++}
++
++static __inline__ int atomic_add_return(int i, atomic_t * v)
++{
++ unsigned long temp, flags;
++
++ local_irq_save(flags);
++ temp = *(long *)v;
++ temp += i;
++ *(long *)v = temp;
++ local_irq_restore(flags);
++
++ return temp;
++}
++
++#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
++
++static __inline__ int atomic_sub_return(int i, atomic_t * v)
++{
++ unsigned long temp, flags;
++
++ local_irq_save(flags);
++ temp = *(long *)v;
++ temp -= i;
++ *(long *)v = temp;
++ local_irq_restore(flags);
++
++ return temp;
++}
++
++#define atomic_dec_return(v) atomic_sub_return(1,(v))
++#define atomic_inc_return(v) atomic_add_return(1,(v))
++
++/*
++ * atomic_inc_and_test - increment and test
++ * @v: pointer of type atomic_t
++ *
++ * Atomically increments @v by 1
++ * and returns true if the result is zero, or false for all
++ * other cases.
++ */
++#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
++
++#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
++#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
++
++#define atomic_inc(v) atomic_add(1,(v))
++#define atomic_dec(v) atomic_sub(1,(v))
++
++static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
++{
++ int ret;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ ret = v->counter;
++ if (likely(ret == old))
++ v->counter = new;
++ local_irq_restore(flags);
++
++ return ret;
++}
++
++#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++
++static inline int atomic_add_unless(atomic_t *v, int a, int u)
++{
++ int ret;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ ret = v->counter;
++ if (ret != u)
++ v->counter += a;
++ local_irq_restore(flags);
++
++ return ret != u;
++}
++#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
++
++static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ *(long *)v &= ~mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ *(long *)v |= mask;
++ local_irq_restore(flags);
++}
++
++/* Atomic operations are already serializing on SH */
++#define smp_mb__before_atomic_dec() barrier()
++#define smp_mb__after_atomic_dec() barrier()
++#define smp_mb__before_atomic_inc() barrier()
++#define smp_mb__after_atomic_inc() barrier()
++
++#include <asm-generic/atomic.h>
++#endif /* __ASM_SH_ATOMIC_H */
+diff --git a/include/asm-nios2nommu/auxvec.h b/include/asm-nios2nommu/auxvec.h
+new file mode 100644
+index 0000000..fc21e4d
+--- /dev/null
++++ b/include/asm-nios2nommu/auxvec.h
+@@ -0,0 +1,4 @@
++#ifndef __ASM_SH_AUXVEC_H
++#define __ASM_SH_AUXVEC_H
++
++#endif /* __ASM_SH_AUXVEC_H */
+diff --git a/include/asm-nios2nommu/bitops.h b/include/asm-nios2nommu/bitops.h
+new file mode 100644
+index 0000000..7bf1862
+--- /dev/null
++++ b/include/asm-nios2nommu/bitops.h
+@@ -0,0 +1,11 @@
++#ifndef __ASM_NIOS2NOMMU_BITOPS_H
++#define __ASM_NIOS2NOMMU_BITOPS_H
++
++#ifdef __KERNEL__
++#include <asm/system.h>
++#include <asm-generic/bitops.h>
++#define smp_mb__before_clear_bit() barrier()
++#define smp_mb__after_clear_bit() barrier()
++#endif /* __KERNEL__ */
++
++#endif /* __ASM_NIOS2NOMMU_BITOPS_H */
+diff --git a/include/asm-nios2nommu/bootinfo.h b/include/asm-nios2nommu/bootinfo.h
+new file mode 100644
+index 0000000..ee8c39e
+--- /dev/null
++++ b/include/asm-nios2nommu/bootinfo.h
+@@ -0,0 +1,2 @@
++
++/* Nothing for nios2nommu */
+diff --git a/include/asm-nios2nommu/bug.h b/include/asm-nios2nommu/bug.h
+new file mode 100644
+index 0000000..d99ab08
+--- /dev/null
++++ b/include/asm-nios2nommu/bug.h
+@@ -0,0 +1,4 @@
++#ifndef _MNIOS2NOMMU_BUG_H
++#define _MNIOS2NOMMU_BUG_H
++#include <asm-generic/bug.h>
++#endif
+diff --git a/include/asm-nios2nommu/bugs.h b/include/asm-nios2nommu/bugs.h
+new file mode 100644
+index 0000000..a0753eb
+--- /dev/null
++++ b/include/asm-nios2nommu/bugs.h
+@@ -0,0 +1,40 @@
++#ifndef __ASM_NIOS_BUGS_H
++#define __ASM_NIOS_BUGS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bugs.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1994 Linus Torvalds
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This is included by init/main.c to check for architecture-dependent bugs.
++ *
++ * Needs:
++ * void check_bugs(void);
++ */
++
++static void check_bugs(void)
++{
++}
++
++#endif
+diff --git a/include/asm-nios2nommu/byteorder.h b/include/asm-nios2nommu/byteorder.h
+new file mode 100644
+index 0000000..960b6d3
+--- /dev/null
++++ b/include/asm-nios2nommu/byteorder.h
+@@ -0,0 +1,38 @@
++#ifndef __ASM_NIOS_BYTEORDER_H
++#define __ASM_NIOS_BYTEORDER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/byteorder.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/types.h>
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
++# define __BYTEORDER_HAS_U64__
++# define __SWAB_64_THRU_32__
++#endif
++
++#include <linux/byteorder/little_endian.h>
++
++#endif
++
+diff --git a/include/asm-nios2nommu/cache.h b/include/asm-nios2nommu/cache.h
+new file mode 100644
+index 0000000..82bbd14
+--- /dev/null
++++ b/include/asm-nios2nommu/cache.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2NOMMU_CACHE_H
++#define __ARCH_NIOS2NOMMU_CACHE_H
++
++#include <asm/nios.h>
++
++/* bytes per L1 cache line */
++#define L1_CACHE_BYTES nasys_icache_line_size /* 32, this need to be at least 1 */
++#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
++#define L1_CACHE_SHIFT 5
++
++
++#define __cacheline_aligned
++#define ____cacheline_aligned
++
++#endif
+diff --git a/include/asm-nios2nommu/cachectl.h b/include/asm-nios2nommu/cachectl.h
+new file mode 100644
+index 0000000..39d7d9d
+--- /dev/null
++++ b/include/asm-nios2nommu/cachectl.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_CACHECTL_H
++#define _NIOS2NOMMU_CACHECTL_H
++
++/* Definitions for the cacheflush system call. */
++
++#define FLUSH_SCOPE_LINE 1 /* Flush a cache line */
++#define FLUSH_SCOPE_PAGE 2 /* Flush a page */
++#define FLUSH_SCOPE_ALL 3 /* Flush the whole cache -- superuser only */
++
++#define FLUSH_CACHE_DATA 1 /* Writeback and flush data cache */
++#define FLUSH_CACHE_INSN 2 /* Flush instruction cache */
++#define FLUSH_CACHE_BOTH 3 /* Flush both caches */
++
++#endif /* _NIOS2NOMMU_CACHECTL_H */
+diff --git a/include/asm-nios2nommu/cacheflush.h b/include/asm-nios2nommu/cacheflush.h
+new file mode 100644
+index 0000000..4543201
+--- /dev/null
++++ b/include/asm-nios2nommu/cacheflush.h
+@@ -0,0 +1,59 @@
++#ifndef _NIOS2NOMMU_CACHEFLUSH_H
++#define _NIOS2NOMMU_CACHEFLUSH_H
++
++/*
++ * Ported from m68knommu.
++ *
++ * (C) Copyright 2003, Microtronix Datacom Ltd.
++ * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/mm.h>
++
++extern void cache_push (unsigned long vaddr, int len);
++extern void dcache_push (unsigned long vaddr, int len);
++extern void icache_push (unsigned long vaddr, int len);
++extern void cache_push_all (void);
++extern void cache_clear (unsigned long paddr, int len);
++
++#define flush_cache_all() __flush_cache_all()
++#define flush_cache_mm(mm) do { } while (0)
++#define flush_cache_range(vma, start, end) cache_push(start, end - start)
++#define flush_cache_page(vma, vmaddr) do { } while (0)
++#define flush_dcache_range(start,end) dcache_push(start, end - start)
++#define flush_dcache_page(page) do { } while (0)
++#define flush_dcache_mmap_lock(mapping) do { } while (0)
++#define flush_dcache_mmap_unlock(mapping) do { } while (0)
++#define flush_icache_range(start,end) cache_push(start, end - start)
++#define flush_icache_page(vma,pg) do { } while (0)
++#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
++
++extern inline void __flush_cache_all(void)
++{
++ cache_push_all();
++}
++
++#endif /* _NIOS2NOMMU_CACHEFLUSH_H */
+diff --git a/include/asm-nios2nommu/checksum.h b/include/asm-nios2nommu/checksum.h
+new file mode 100644
+index 0000000..1f6879e
+--- /dev/null
++++ b/include/asm-nios2nommu/checksum.h
+@@ -0,0 +1,320 @@
++#ifndef __NIOS2_CHECKSUM_H
++#define __NIOS2_CHECKSUM_H
++
++/* checksum.h: IP/UDP/TCP checksum routines on the NIOS.
++ *
++ * Copyright(C) 1995 Linus Torvalds
++ * Copyright(C) 1995 Miguel de Icaza
++ * Copyright(C) 1996 David S. Miller
++ * Copyright(C) 2001 Ken Hill
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * derived from:
++ * Alpha checksum c-code
++ * ix86 inline assembly
++ * Spar nommu
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++
++extern inline unsigned short csum_tcpudp_magic(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++" add %0, %3, %0\n"
++" bgeu %0, %3, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %4, %0\n"
++" bgeu %0, %4, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %5, %0\n"
++" bgeu %0, %5, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++/*
++ We need the carry from the addition of 16-bit
++ significant addition, so we zap out the low bits
++ in one half, zap out the high bits in another,
++ shift them both up to the top 16-bits of a word
++ and do the carry producing addition, finally
++ shift the result back down to the low 16-bits.
++
++ Actually, we can further optimize away two shifts
++ because we know the low bits of the original
++ value will be added to zero-only bits so cannot
++ affect the addition result nor the final carry
++ bit.
++*/
++" slli %1,%0, 16\n" /* Need a copy to fold with */
++ /* Bring the LOW 16 bits up */
++" add %0, %1, %0\n" /* add and set carry, neat eh? */
++" cmpltu r15, %0, %1\n" /* get remaining carry bit */
++" srli %0, %0, 16\n" /* shift back down the result */
++" add %0, %0, r15\n"
++" nor %0, %0, %0\n" /* negate */
++ : "=&r" (sum), "=&r" (saddr)
++ : "0" (sum), "1" (saddr), "r" (ntohl(len+proto)), "r" (daddr)
++ : "r15");
++ return ((unsigned short) sum);
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++ extern inline unsigned short from32to16(unsigned long x)
++ {
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r15, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r15\n"
++ : "=r" (x)
++ : "r" (x << 16), "0" (x)
++ : "r15");
++ return x;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern inline unsigned long do_csum(const unsigned char * buff, int len)
++{
++ int odd, count;
++ unsigned long result = 0;
++
++ barrier();
++ if (len <= 0)
++ goto out;
++ odd = 1 & (unsigned long) buff;
++ if (odd) {
++////result = *buff; // dgt: Big endian
++ result = *buff << 8; // dgt: Little endian
++
++ len--;
++ buff++;
++ }
++ count = len >> 1; /* nr of 16-bit words.. */
++ if (count) {
++ if (2 & (unsigned long) buff) {
++ result += *(unsigned short *) buff;
++ count--;
++ len -= 2;
++ buff += 2;
++ }
++ count >>= 1; /* nr of 32-bit words.. */
++ if (count) {
++ unsigned long carry = 0;
++ do {
++ unsigned long w = *(unsigned long *) buff;
++ count--;
++ buff += 4;
++ result += carry;
++ result += w;
++ carry = (w > result);
++ } while (count);
++ result += carry;
++ result = (result & 0xffff) + (result >> 16);
++ }
++ if (len & 2) {
++ result += *(unsigned short *) buff;
++ buff += 2;
++ }
++ }
++ if (len & 1)
++ result += *buff; /* This is little machine, byte is right */
++ result = from32to16(result);
++ if (odd)
++ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
++out:
++ return result;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/* ihl is always 5 or greater, almost always is 5, iph is always word
++ * aligned but can fail to be dword aligned very often.
++ */
++
++ extern inline unsigned short ip_fast_csum(const unsigned char *iph, unsigned int ihl)
++ {
++ unsigned int sum;
++
++ barrier();
++ __asm__ __volatile__(
++" andi r8, %1, 2\n" /* Remember original alignment */
++" ldw %0, (%1)\n" /* 16 or 32 bit boundary */
++" beq r8, r0, 1f\n" /* Aligned on 32 bit boundary, go */
++" srli %0, %0, 16\n" /* Get correct 16 bits */
++" addi %2, %2, -1\n" /* Take off for 4 bytes, pickup last 2 at end */
++" addi %1, %1, 2\n" /* Adjust pointer to 32 bit boundary */
++" br 2f\n"
++"1:\n"
++" addi %2, %2, -1\n"
++" addi %1, %1, 4\n" /* Bump ptr a long word */
++"2:\n"
++" ldw r9, (%1)\n"
++"1:\n"
++" add %0, r9, %0\n"
++" bgeu %0, r9, 2f\n"
++" addi %0, %0, 1\n"
++"2:\n"
++" addi %1, %1, 4\n"
++" addi %2, %2, -1\n"
++" ldw r9, (%1)\n"
++" bne %2, r0, 1b\n"
++" beq r8, r0, 1f\n" /* 32 bit boundary time to leave */
++" srli r9, r9, 16\n" /* 16 bit boundary, get correct 16 bits */
++" add %0, r9, %0\n"
++" bgeu %0, r9, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++" slli %2, %0, 16\n"
++" add %0, %2, %0\n"
++" cmpltu r8, %0, %2\n"
++" srli %0, %0, 16\n"
++" add %0, %0, r8\n"
++" nor %0, %0, %0\n"
++ : "=&r" (sum), "=&r" (iph), "=&r" (ihl)
++ : "1" (iph), "2" (ihl)
++ : "r8", "r9");
++ return sum;
++ barrier();
++ }
++
++/*these 2 functions are now in checksum.c */
++unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
++unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * the same as csum_partial_copy, but copies from user space.
++ *
++ * here even more important to align src and dst on a 32-bit (or even
++ * better 64-bit) boundary
++ */
++extern inline unsigned int
++csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
++{
++ barrier();
++ if (csum_err) *csum_err = 0;
++ memcpy(dst, src, len);
++ return csum_partial(dst, len, sum);
++ barrier();
++}
++
++#define csum_partial_copy_nocheck(src, dst, len, sum) \
++ csum_partial_copy ((src), (dst), (len), (sum))
++
++
++/*
++ * this routine is used for miscellaneous IP-like checksums, mainly
++ * in icmp.c
++ */
++
++extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
++{
++ barrier();
++ return ~from32to16(do_csum(buff,len));
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++#define csum_partial_copy_fromuser(s, d, l, w) \
++ csum_partial_copy((char *) (s), (d), (l), (w))
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/*
++ * Fold a partial checksum without adding pseudo headers
++ */
++extern __inline__ unsigned int csum_fold(unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r8\n"
++ "nor %0, %0, %0\n"
++ : "=r" (sum)
++ : "r" (sum << 16), "0" (sum)
++ : "r8");
++ return sum;
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %2, %0\n"
++ "cmpltu r8, %0, %2\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %3, %0\n"
++ "cmpltu r8, %0, %3\n"
++ "add %0, %0, r8\n" /* add carry */
++ : "=r" (sum), "=r" (saddr)
++ : "r" (daddr), "r" ( (ntohs(len)<<16) + (proto*256) ),
++ "0" (sum),
++ "1" (saddr)
++ : "r8");
++
++ return sum;
++ barrier();
++}
++
++
++#endif /* (__NIOS2_CHECKSUM_H) */
+diff --git a/include/asm-nios2nommu/cprefix.h b/include/asm-nios2nommu/cprefix.h
+new file mode 100644
+index 0000000..4983211
+--- /dev/null
++++ b/include/asm-nios2nommu/cprefix.h
+@@ -0,0 +1,38 @@
++/* cprefix.h: This file is included by assembly source which needs
++ * to know what the c-label prefixes are. The newer versions
++ * of cpp that come with gcc predefine such things to help
++ * us out. The reason this stuff is needed is to make
++ * solaris compiles of the kernel work.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_CPREFIX_H
++#define __NIOS2_CPREFIX_H
++
++#define C_LABEL_PREFIX
++
++#define CONCAT(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a##b
++
++#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name)
++
++#endif /* !(__NIOS2_CPREFIX_H) */
+diff --git a/include/asm-nios2nommu/cpumask.h b/include/asm-nios2nommu/cpumask.h
+new file mode 100644
+index 0000000..86fb365
+--- /dev/null
++++ b/include/asm-nios2nommu/cpumask.h
+@@ -0,0 +1,28 @@
++/*
++ * All rights reserved.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_CPUMASK_H
++#define _ASM_NIOS2NOMMU_CPUMASK_H
++
++#include <asm-generic/cpumask.h>
++
++#endif /* _ASM_NIOS2NOMMU_CPUMASK_H */
+diff --git a/include/asm-nios2nommu/cputime.h b/include/asm-nios2nommu/cputime.h
+new file mode 100644
+index 0000000..370e4f2
+--- /dev/null
++++ b/include/asm-nios2nommu/cputime.h
+@@ -0,0 +1,31 @@
++/*
++ * cputime.h
++ * (C) Copyright 2004, Microtronix Datacom Ltd.
++ *
++ * Taken from m68knommu
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_CPUTIME_H
++#define __NIOS2NOMMU_CPUTIME_H
++
++#include <asm-generic/cputime.h>
++
++#endif /* __NIOS@NOMMU_CPUTIME_H */
+diff --git a/include/asm-nios2nommu/current.h b/include/asm-nios2nommu/current.h
+new file mode 100644
+index 0000000..5ac1dbc
+--- /dev/null
++++ b/include/asm-nios2nommu/current.h
+@@ -0,0 +1,39 @@
++#ifndef _NIOS2NOMMU_CURRENT_H
++#define _NIOS2NOMMU_CURRENT_H
++/*
++ * current.h
++ * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
++ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
++ * (C) Copyright 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/thread_info.h>
++
++struct task_struct;
++
++static inline struct task_struct *get_current(void)
++{
++ return(current_thread_info()->task);
++}
++
++#define current get_current()
++
++#endif /* _NIOS2NOMMU_CURRENT_H */
+diff --git a/include/asm-nios2nommu/delay.h b/include/asm-nios2nommu/delay.h
+new file mode 100644
+index 0000000..da0a184
+--- /dev/null
++++ b/include/asm-nios2nommu/delay.h
+@@ -0,0 +1,96 @@
++#ifndef _NIOS_DELAY_H
++#define _NIOS_DELAY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/delay.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/param.h>
++
++extern __inline__ void __delay(unsigned long loops)
++{
++ int dummy;
++
++ __asm__ __volatile__(
++ "1: \n\t"
++ " beq %0,zero,2f\n\t"
++ " addi %0, %0, -1\n\t"
++ " br 1b\n\t"
++ "2: \n\t"
++
++ : "=r" (dummy) /* Need output for optimizer */
++
++ : "0" (loops) /* %0 Input */
++ );
++}
++
++/*
++ * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so
++ * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32.
++ *
++ * The mul instruction gives us loops = (a * b) / 2^32.
++ * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226
++ * because this lets us support a wide range of HZ and
++ * loops_per_jiffy values without either a or b overflowing 2^32.
++ * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and
++ * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280
++ * (which corresponds to ~3800 bogomips at HZ = 100).
++ * -- paulus
++ */
++#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */
++#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */
++
++extern unsigned long loops_per_jiffy;
++
++extern __inline__ void __udelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 226));
++ __delay(loops);
++}
++
++extern __inline__ void __ndelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 5));
++ __delay(loops);
++}
++
++extern void __bad_udelay(void); /* deliberately undefined */
++extern void __bad_ndelay(void); /* deliberately undefined */
++
++#define udelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_UDELAY? __bad_udelay(): __udelay((n) * (19 * HZ))) : \
++ __udelay((n) * (19 * HZ)))
++
++#define ndelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_NDELAY? __bad_ndelay(): __ndelay((n) * HZ)) : \
++ __ndelay((n) * HZ))
++
++#define muldiv(a, b, c) (((a)*(b))/(c))
++
++#endif /* defined(_NIOS_DELAY_H) */
+diff --git a/include/asm-nios2nommu/device.h b/include/asm-nios2nommu/device.h
+new file mode 100644
+index 0000000..d8f9872
+--- /dev/null
++++ b/include/asm-nios2nommu/device.h
+@@ -0,0 +1,7 @@
++/*
++ * Arch specific extensions to struct device
++ *
++ * This file is released under the GPLv2
++ */
++#include <asm-generic/device.h>
++
+diff --git a/include/asm-nios2nommu/div64.h b/include/asm-nios2nommu/div64.h
+new file mode 100644
+index 0000000..68d72e4
+--- /dev/null
++++ b/include/asm-nios2nommu/div64.h
+@@ -0,0 +1,31 @@
++#ifndef __ASMNIOS_DIV64_H
++#define __ASMNIOS_DIV64_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/div64.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/div64.h>
++
++#endif
++
+diff --git a/include/asm-nios2nommu/dma-mapping.h b/include/asm-nios2nommu/dma-mapping.h
+new file mode 100644
+index 0000000..6289370
+--- /dev/null
++++ b/include/asm-nios2nommu/dma-mapping.h
+@@ -0,0 +1,79 @@
++#ifndef _ASM_DMA_MAPPING_H
++#define _ASM_DMA_MAPPING_H
++
++#include <asm/scatterlist.h>
++#include <asm/cache.h>
++
++void *dma_alloc_noncoherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, gfp_t flag);
++
++void dma_free_noncoherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
++
++void *dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, gfp_t flag);
++
++void dma_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
++
++extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
++ enum dma_data_direction direction);
++extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
++ size_t size, enum dma_data_direction direction);
++extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction);
++extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size, enum dma_data_direction direction);
++extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
++ size_t size, enum dma_data_direction direction);
++extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
++ int nhwentries, enum dma_data_direction direction);
++extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
++ size_t size, enum dma_data_direction direction);
++extern void dma_sync_single_for_device(struct device *dev,
++ dma_addr_t dma_handle, size_t size, enum dma_data_direction direction);
++extern void dma_sync_single_range_for_cpu(struct device *dev,
++ dma_addr_t dma_handle, unsigned long offset, size_t size,
++ enum dma_data_direction direction);
++extern void dma_sync_single_range_for_device(struct device *dev,
++ dma_addr_t dma_handle, unsigned long offset, size_t size,
++ enum dma_data_direction direction);
++extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
++ int nelems, enum dma_data_direction direction);
++extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
++ int nelems, enum dma_data_direction direction);
++extern int dma_mapping_error(dma_addr_t dma_addr);
++extern int dma_supported(struct device *dev, u64 mask);
++
++static inline int
++dma_set_mask(struct device *dev, u64 mask)
++{
++ if(!dev->dma_mask || !dma_supported(dev, mask))
++ return -EIO;
++
++ *dev->dma_mask = mask;
++
++ return 0;
++}
++
++static inline int
++dma_get_cache_alignment(void)
++{
++ /* XXX Largest on any MIPS */
++ return 128;
++}
++
++extern int dma_is_consistent(dma_addr_t dma_addr);
++
++extern void dma_cache_sync(void *vaddr, size_t size,
++ enum dma_data_direction direction);
++
++// #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++//
++// extern int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++// dma_addr_t device_addr, size_t size, int flags);
++// extern void dma_release_declared_memory(struct device *dev);
++// extern void * dma_mark_declared_memory_occupied(struct device *dev,
++// dma_addr_t device_addr, size_t size);
++
++#endif /* _ASM_DMA_MAPPING_H */
+diff --git a/include/asm-nios2nommu/dma.h b/include/asm-nios2nommu/dma.h
+new file mode 100644
+index 0000000..ea098d5
+--- /dev/null
++++ b/include/asm-nios2nommu/dma.h
+@@ -0,0 +1,63 @@
++/* $Id: dma.h,v 1.1 2006/07/05 06:20:25 gerg Exp $
++ *
++ * Copyright 2004 (C) Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2_DMA_H
++#define _ASM_NIOS2_DMA_H
++
++#include <linux/kernel.h>
++#include <asm/asm-offsets.h>
++
++#define MAX_DMA_ADDRESS (LINUX_SDRAM_END)
++
++int request_dma(unsigned int, const char *);
++void free_dma(unsigned int);
++void enable_dma(unsigned int dmanr);
++void disable_dma(unsigned int dmanr);
++void set_dma_count(unsigned int dmanr, unsigned int count);
++int get_dma_residue(unsigned int dmanr);
++void nios2_set_dma_data_width(unsigned int dmanr, unsigned int width);
++
++void nios2_set_dma_handler(unsigned int dmanr, int (*handler)(void*, int), void* user);
++int nios2_request_dma(const char *);
++
++void nios2_set_dma_mode(unsigned int dmanr, unsigned int mode);
++void nios2_set_dma_rcon(unsigned int dmanr, unsigned int set);
++void nios2_set_dma_wcon(unsigned int dmanr, unsigned int set);
++void nios2_set_dma_raddr(unsigned int dmanr, unsigned int a);
++void nios2_set_dma_waddr(unsigned int dmanr, unsigned int a);
++
++static inline unsigned long claim_dma_lock(void)
++{
++}
++
++static inline void release_dma_lock(unsigned long flags)
++{
++}
++
++#ifdef CONFIG_PCI
++extern int isa_dma_bridge_buggy;
++#else
++#define isa_dma_bridge_buggy (0)
++#endif
++
++#endif /* !(_ASM_NIOS2_DMA_H) */
+diff --git a/include/asm-nios2nommu/elf.h b/include/asm-nios2nommu/elf.h
+new file mode 100644
+index 0000000..94b2ac0
+--- /dev/null
++++ b/include/asm-nios2nommu/elf.h
+@@ -0,0 +1,140 @@
++#ifndef __NIOS2_ELF_H
++#define __NIOS2_ELF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/elf.h
++ *
++ * Nio2 ELF relocation types
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ * Mar/18/2004 xwt NiosII relocation types added
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm/ptrace.h>
++#include <asm/user.h>
++
++#define R_NIOS2_NONE 0
++#define R_NIOS2_S16 1
++#define R_NIOS2_U16 2
++#define R_NIOS2_PCREL16 3
++#define R_NIOS2_CALL26 4
++#define R_NIOS2_IMM5 5
++#define R_NIOS2_CACHE_OPX 6
++#define R_NIOS2_IMM6 7
++#define R_NIOS2_IMM8 8
++#define R_NIOS2_HI16 9
++#define R_NIOS2_LO16 10
++#define R_NIOS2_HIADJ16 11
++#define R_NIOS2_BFD_RELOC_32 12
++#define R_NIOS2_BFD_RELOC_16 13
++#define R_NIOS2_BFD_RELOC_8 14
++#define R_NIOS2_GPREL 15
++#define R_NIOS2_GNU_VTINHERIT 16
++#define R_NIOS2_GNU_VTENTRY 17
++#define R_NIOS2_UJMP 18
++#define R_NIOS2_CJMP 19
++#define R_NIOS2_CALLR 20
++#define R_NIOS2_ALIGN 21
++/* Keep this the last entry. */
++#define R_NIOS2_NUM 22
++
++typedef unsigned long elf_greg_t;
++
++#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++typedef unsigned long elf_fpregset_t;
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++#define elf_check_arch(x) \
++ ((x)->e_machine == EM_ALTERA_NIOS2)
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2LSB
++#define ELF_ARCH EM_ALTERA_NIOS2
++
++#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
++ use of this is to invoke "./ld.so someprog" to test out a new version of
++ the loader. We need to make sure that it is out of the way of the program
++ that it will "exec", and that there is sufficient room for the brk. */
++
++#define ELF_ET_DYN_BASE 0xD0000000UL
++
++/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
++ now struct_user_regs, they are different) */
++
++#define ELF_CORE_COPY_REGS(pr_reg, regs) \
++ /* Bleech. */ \
++ pr_reg[0] = regs->r1; \
++ pr_reg[1] = regs->r2; \
++ pr_reg[2] = regs->r3; \
++ pr_reg[3] = regs->r4; \
++ pr_reg[4] = regs->r5; \
++ pr_reg[5] = regs->r6; \
++ pr_reg[6] = regs->r7; \
++ pr_reg[7] = regs->r8; \
++ pr_reg[8] = regs->r9; \
++ pr_reg[9] = regs->r10; \
++ pr_reg[10] = regs->r11; \
++ pr_reg[11] = regs->r12; \
++ pr_reg[12] = regs->r13; \
++ pr_reg[13] = regs->r14; \
++ pr_reg[14] = regs->r15; \
++ pr_reg[23] = regs->sp; \
++ pr_reg[26] = regs->estatus; \
++ { \
++ struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \
++ pr_reg[15] = sw->r16; \
++ pr_reg[16] = sw->r17; \
++ pr_reg[17] = sw->r18; \
++ pr_reg[18] = sw->r19; \
++ pr_reg[19] = sw->r20; \
++ pr_reg[20] = sw->r21; \
++ pr_reg[21] = sw->r22; \
++ pr_reg[22] = sw->r23; \
++ pr_reg[24] = sw->fp; \
++ pr_reg[25] = sw->gp; \
++ }
++
++/* This yields a mask that user programs can use to figure out what
++ instruction set this cpu supports. */
++
++#define ELF_HWCAP (0)
++
++/* This yields a string that ld.so will use to load implementation
++ specific libraries for optimization. This is more specific in
++ intent than poking at uname or /proc/cpuinfo. */
++
++#define ELF_PLATFORM (NULL)
++
++#ifdef __KERNEL__
++#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
++#endif
++
++#endif
+diff --git a/include/asm-nios2nommu/emergency-restart.h b/include/asm-nios2nommu/emergency-restart.h
+new file mode 100644
+index 0000000..108d8c4
+--- /dev/null
++++ b/include/asm-nios2nommu/emergency-restart.h
+@@ -0,0 +1,6 @@
++#ifndef _ASM_EMERGENCY_RESTART_H
++#define _ASM_EMERGENCY_RESTART_H
++
++#include <asm-generic/emergency-restart.h>
++
++#endif /* _ASM_EMERGENCY_RESTART_H */
+diff --git a/include/asm-nios2nommu/entry.h b/include/asm-nios2nommu/entry.h
+new file mode 100644
+index 0000000..4b1773f
+--- /dev/null
++++ b/include/asm-nios2nommu/entry.h
+@@ -0,0 +1,187 @@
++/*
++ * Hacked from m68knommu port.
++ *
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_ENTRY_H
++#define __NIOS2NOMMU_ENTRY_H
++
++#ifdef __ASSEMBLY__
++
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/asm-offsets.h>
++
++/*
++ * Stack layout in 'ret_from_exception':
++ *
++ * This allows access to the syscall arguments in registers r4-r8
++ *
++ * 0(sp) - r8
++ * 4(sp) - r9
++ * 8(sp) - r10
++ * C(sp) - r11
++ * 10(sp) - r12
++ * 14(sp) - r13
++ * 18(sp) - r14
++ * 1C(sp) - r15
++ * 20(sp) - r1
++ * 24(sp) - r2
++ * 28(sp) - r3
++ * 2C(sp) - r4
++ * 30(sp) - r5
++ * 34(sp) - r6
++ * 38(sp) - r7
++ * 3C(sp) - orig_r2
++ * 40(sp) - ra
++ * 44(sp) - fp
++ * 48(sp) - sp
++ * 4C(sp) - gp
++ * 50(sp) - estatus
++ * 54(sp) - status_extension
++ * 58(sp) - ea
++ *
++ */
++
++/* process bits for task_struct.flags */
++PF_TRACESYS_OFF = 3
++PF_TRACESYS_BIT = 5
++PF_PTRACED_OFF = 3
++PF_PTRACED_BIT = 4
++PF_DTRACE_OFF = 1
++PF_DTRACE_BIT = 5
++
++LENOSYS = 38
++
++/*
++ * This defines the normal kernel pt-regs layout.
++ *
++ */
++
++/*
++ * Standard Nios2 interrupt entry and exit macros.
++ * Must be called with interrupts disabled.
++ */
++.macro SAVE_ALL
++ movia r24,status_extension // Read status extension
++ ldw r24,0(r24)
++ andi r24,r24,PS_S_ASM
++ bne r24,r0,1f // In supervisor mode, already on kernel stack
++ movia r24,_current_thread // Switch to current kernel stack
++ ldw r24,0(r24) // using the thread_info
++ addi r24,r24,THREAD_SIZE_ASM-PT_REGS_SIZE
++ stw sp,PT_SP(r24) // Save user stack before changing
++ mov sp,r24
++ br 2f
++
++1: mov r24,sp
++ addi sp,sp,-PT_REGS_SIZE // Backup the kernel stack pointer
++ stw r24,PT_SP(sp)
++2: stw r1,PT_R1(sp)
++ stw r2,PT_R2(sp)
++ stw r3,PT_R3(sp)
++ stw r4,PT_R4(sp)
++ stw r5,PT_R5(sp)
++ stw r6,PT_R6(sp)
++ stw r7,PT_R7(sp)
++ stw r8,PT_R8(sp)
++ stw r9,PT_R9(sp)
++ stw r10,PT_R10(sp)
++ stw r11,PT_R11(sp)
++ stw r12,PT_R12(sp)
++ stw r13,PT_R13(sp)
++ stw r14,PT_R14(sp)
++ stw r15,PT_R15(sp)
++ stw r2,PT_ORIG_R2(sp)
++ stw ra,PT_RA(sp)
++ stw fp,PT_FP(sp)
++ stw gp,PT_GP(sp)
++ rdctl r24,estatus
++ stw r24,PT_ESTATUS(sp)
++ movia r24,status_extension // Read status extension
++ ldw r1,0(r24)
++ stw r1,PT_STATUS_EXTENSION(sp) // Store user/supervisor status
++ ORI32 r1,r1,PS_S_ASM // Set supervisor mode
++ stw r1,0(r24)
++ stw ea,PT_EA(sp)
++.endm
++
++.macro RESTORE_ALL
++ ldw r1,PT_STATUS_EXTENSION(sp) // Restore user/supervisor status
++ movia r24,status_extension
++ stw r1,0(r24)
++ ldw r1,PT_R1(sp) // Restore registers
++ ldw r2,PT_R2(sp)
++ ldw r3,PT_R3(sp)
++ ldw r4,PT_R4(sp)
++ ldw r5,PT_R5(sp)
++ ldw r6,PT_R6(sp)
++ ldw r7,PT_R7(sp)
++ ldw r8,PT_R8(sp)
++ ldw r9,PT_R9(sp)
++ ldw r10,PT_R10(sp)
++ ldw r11,PT_R11(sp)
++ ldw r12,PT_R12(sp)
++ ldw r13,PT_R13(sp)
++ ldw r14,PT_R14(sp)
++ ldw r15,PT_R15(sp)
++ ldw ra,PT_RA(sp)
++ ldw fp,PT_FP(sp)
++ ldw gp,PT_GP(sp)
++ ldw r24,PT_ESTATUS(sp)
++ wrctl estatus,r24
++ ldw ea,PT_EA(sp)
++ ldw sp,PT_SP(sp) // Restore sp last
++.endm
++
++.macro SAVE_SWITCH_STACK
++ addi sp,sp,-SWITCH_STACK_SIZE
++ stw r16,SW_R16(sp)
++ stw r17,SW_R17(sp)
++ stw r18,SW_R18(sp)
++ stw r19,SW_R19(sp)
++ stw r20,SW_R20(sp)
++ stw r21,SW_R21(sp)
++ stw r22,SW_R22(sp)
++ stw r23,SW_R23(sp)
++ stw fp,SW_FP(sp)
++ stw gp,SW_GP(sp)
++ stw ra,SW_RA(sp)
++.endm
++
++.macro RESTORE_SWITCH_STACK
++ ldw r16,SW_R16(sp)
++ ldw r17,SW_R17(sp)
++ ldw r18,SW_R18(sp)
++ ldw r19,SW_R19(sp)
++ ldw r20,SW_R20(sp)
++ ldw r21,SW_R21(sp)
++ ldw r22,SW_R22(sp)
++ ldw r23,SW_R23(sp)
++ ldw fp,SW_FP(sp)
++ ldw gp,SW_GP(sp)
++ ldw ra,SW_RA(sp)
++ addi sp,sp,SWITCH_STACK_SIZE
++.endm
++
++#endif /* __ASSEMBLY__ */
++#endif /* __NIOS2NOMMU_ENTRY_H */
+diff --git a/include/asm-nios2nommu/errno.h b/include/asm-nios2nommu/errno.h
+new file mode 100644
+index 0000000..c2caf21
+--- /dev/null
++++ b/include/asm-nios2nommu/errno.h
+@@ -0,0 +1,6 @@
++#ifndef _NIOS2NOMMU_ERRNO_H
++#define _NIOS2NOMMU_ERRNO_H
++
++#include <asm-generic/errno.h>
++
++#endif /* _NIOS2NOMMU_ERRNO_H */
+diff --git a/include/asm-nios2nommu/fcntl.h b/include/asm-nios2nommu/fcntl.h
+new file mode 100644
+index 0000000..9d98af2
+--- /dev/null
++++ b/include/asm-nios2nommu/fcntl.h
+@@ -0,0 +1,11 @@
++#ifndef _NIOS2_FCNTL_H
++#define _NIOS2_FCNTL_H
++
++#define O_DIRECTORY 040000 /* must be a directory */
++#define O_NOFOLLOW 0100000 /* don't follow links */
++#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
++#define O_LARGEFILE 0400000
++
++#include <asm-generic/fcntl.h>
++
++#endif /* _NIOS2_FCNTL_H */
+diff --git a/include/asm-nios2nommu/flat.h b/include/asm-nios2nommu/flat.h
+new file mode 100644
+index 0000000..681329a
+--- /dev/null
++++ b/include/asm-nios2nommu/flat.h
+@@ -0,0 +1,129 @@
++/*
++ * include/asm-nios2nommu/flat.h -- uClinux bFLT relocations
++ *
++ * Copyright (C) 2004,05 Microtronix Datacom Ltd
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License. See the file COPYING in the main directory of this
++ * archive for more details.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#ifndef __NIOS2_FLAT_H__
++#define __NIOS2_FLAT_H__
++
++#define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
++
++/* The stack is 64-bit aligned for Nios II, so (sp - 1) shall
++ * be 64-bit aligned, where -1 is for argc
++ */
++#define flat_stack_align(sp) (sp = (unsigned long *)(((unsigned long)sp - 1) & (-8)))
++
++/* The uClibc port for Nios II expects the argc is followed by argv and envp */
++#define flat_argvp_envp_on_stack() 1
++
++#define flat_old_ram_flag(flags) (flags)
++
++/* We store the type of relocation in the top 4 bits of the `relval.' */
++
++/* Convert a relocation entry into an address. */
++static inline unsigned long
++flat_get_relocate_addr (unsigned long relval)
++{
++ return relval & 0x0fffffff; /* Mask out top 4-bits */
++}
++
++#define FLAT_NIOS2_RELOC_TYPE(relval) ((relval) >> 28)
++
++#define FLAT_NIOS2_R_32 0 /* Normal 32-bit reloc */
++#define FLAT_NIOS2_R_HI_LO 1 /* High 16-bits + low 16-bits field */
++#define FLAT_NIOS2_R_HIADJ_LO 2 /* High 16-bits adjust + low 16-bits field */
++#define FLAT_NIOS2_R_CALL26 4 /* Call imm26 */
++
++#define flat_set_persistent(relval, p) 0
++
++/* Extract the address to be relocated from the symbol reference at rp;
++ * relval is the raw relocation-table entry from which RP is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
++ unsigned long relval,
++ unsigned long flags,
++ unsigned long *persistent)
++{
++ switch (FLAT_NIOS2_RELOC_TYPE(relval))
++ {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. The loader expect it in bigger endian */
++ return htonl(*rp);
++
++ case FLAT_NIOS2_R_HI_LO:
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ return htonl ((((rp[0] >> 6) & 0xFFFF) << 16 ) |
++ ((rp[1] >> 6) & 0xFFFF));
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ unsigned int low, high;
++ high = (rp[0] >> 6) & 0xFFFF;
++ low = (rp[1] >> 6) & 0xFFFF;
++
++ if ((low >> 15) & 1) high--;
++
++ return htonl ((high << 16 ) | low );
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the 26-bit immediate value is actually 28-bit */
++ return htonl(((*rp) >> 6) << 2);
++
++ default:
++ return ~0; /* bogus value */
++ }
++}
++
++/* Insert the address addr into the symbol reference at rp;
++ * relval is the raw relocation-table entry from which rp is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
++ unsigned long relval)
++{
++ unsigned long exist_val;
++ switch (FLAT_NIOS2_RELOC_TYPE (relval)) {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. */
++ *rp = addr;
++ break;
++
++ case FLAT_NIOS2_R_HI_LO:
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | (addr >> 16)) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ unsigned int high = (addr >> 16);
++ if ((addr >> 15) & 1)
++ high = (high + 1) & 0xFFFF;
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | high) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the opcode of CALL is 0, so just store the value */
++ *rp = ((addr >> 2) << 6);
++ break;
++ }
++}
++
++#endif /* __NIOS2_FLAT_H__ */
+diff --git a/include/asm-nios2nommu/futex.h b/include/asm-nios2nommu/futex.h
+new file mode 100644
+index 0000000..6a332a9
+--- /dev/null
++++ b/include/asm-nios2nommu/futex.h
+@@ -0,0 +1,6 @@
++#ifndef _ASM_FUTEX_H
++#define _ASM_FUTEX_H
++
++#include <asm-generic/futex.h>
++
++#endif
+diff --git a/include/asm-nios2nommu/gpio.h b/include/asm-nios2nommu/gpio.h
+new file mode 100644
+index 0000000..b91937b
+--- /dev/null
++++ b/include/asm-nios2nommu/gpio.h
+@@ -0,0 +1,11 @@
++#ifndef _ASM_GPIO_H_
++#define _ASM_GPIO_H_ 1
++
++
++struct gpio_i2c_pins {
++ unsigned sda_pin;
++ unsigned scl_pin;
++};
++
++#endif /*_ASM_GPIO_*/
++
+diff --git a/include/asm-nios2nommu/hardirq.h b/include/asm-nios2nommu/hardirq.h
+new file mode 100644
+index 0000000..0041f51
+--- /dev/null
++++ b/include/asm-nios2nommu/hardirq.h
+@@ -0,0 +1,43 @@
++/*
++ * Ported from m68knommu
++ *
++ * Copyright (C) 2003, Microtronix Datacom Ltd.
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HARDIRQ_H
++#define __NIOS2_HARDIRQ_H
++
++#include <linux/cache.h>
++#include <linux/threads.h>
++
++typedef struct {
++ unsigned int __softirq_pending;
++} ____cacheline_aligned irq_cpustat_t;
++
++#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
++
++#define HARDIRQ_BITS 8
++
++#ifdef CONFIG_SMP
++# error nios2nommu SMP is not available
++#endif /* CONFIG_SMP */
++
++#endif /* __NIOS2_HARDIRQ_H */
+diff --git a/include/asm-nios2nommu/hdreg.h b/include/asm-nios2nommu/hdreg.h
+new file mode 100644
+index 0000000..b4d910a
+--- /dev/null
++++ b/include/asm-nios2nommu/hdreg.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2002 Wentau Xu (www.microtronix.com)
++ * copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HDREG_H
++#define __NIOS2_HDREG_H
++
++typedef unsigned long ide_ioreg_t;
++
++#endif /* __NIOS2_HDREG_H */
+diff --git a/include/asm-nios2nommu/hw_irq.h b/include/asm-nios2nommu/hw_irq.h
+new file mode 100644
+index 0000000..d2fd3be
+--- /dev/null
++++ b/include/asm-nios2nommu/hw_irq.h
+@@ -0,0 +1,16 @@
++#ifndef _ASM_HW_IRQ_H
++#define _ASM_HW_IRQ_H
++
++/*
++ * linux/include/asm/hw_irq.h
++ *
++ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
++ *
++ * moved some of the old arch/i386/kernel/irq.h to here. VY
++ *
++ * IRQ/IPI changes taken from work by Thomas Radke
++ * <tomsoft@informatik.tu-chemnitz.de>
++ */
++
++
++#endif /* _ASM_HW_IRQ_H */
+diff --git a/include/asm-nios2nommu/ide.h b/include/asm-nios2nommu/ide.h
+new file mode 100644
+index 0000000..f8ef9ad
+--- /dev/null
++++ b/include/asm-nios2nommu/ide.h
+@@ -0,0 +1,40 @@
++/*
++ * linux/include/asm-niosnommu2/ide.h
++ *
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASMNIOS2_IDE_H
++#define __ASMNIOS2_IDE_H
++
++#ifdef __KERNEL__
++#undef MAX_HWIFS /* we're going to force it */
++
++#ifndef MAX_HWIFS
++#define MAX_HWIFS 1
++#endif
++
++#include <asm-generic/ide_iops.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASMNIOS2_IDE_H */
+diff --git a/include/asm-nios2nommu/init.h b/include/asm-nios2nommu/init.h
+new file mode 100644
+index 0000000..8641f4f
+--- /dev/null
++++ b/include/asm-nios2nommu/init.h
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++#error "<asm/init.h> should never be used - use <linux/init.h> instead"
+diff --git a/include/asm-nios2nommu/io.h b/include/asm-nios2nommu/io.h
+new file mode 100644
+index 0000000..d0e3741
+--- /dev/null
++++ b/include/asm-nios2nommu/io.h
+@@ -0,0 +1,277 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_IO_H
++#define __NIOS2_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/kernel.h>
++
++#include <asm/page.h> /* IO address mapping routines need this */
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++extern void insw(unsigned long port, void *dst, unsigned long count);
++extern void outsw(unsigned long port, void *src, unsigned long count);
++extern void insl(unsigned long port, void *dst, unsigned long count);
++extern void outsl(unsigned long port, void *src, unsigned long count);
++
++#define readsb(p,d,l) insb(p,d,l)
++#define readsw(p,d,l) insw(p,d,l)
++#define readsl(p,d,l) insl(p,d,l)
++#define writesb(p,d,l) outsb(p,d,l)
++#define writesw(p,d,l) outsw(p,d,l)
++#define writesl(p,d,l) outsl(p,d,l)
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#endif /* __KERNEL__ */
++/* IO macros are needed by userspace programs */
++
++/*
++ * readX/writeX() are used to access memory mapped devices. On some
++ * architectures the memory mapped IO stuff needs to be accessed
++ * differently. On the Nios architecture, we just read/write the
++ * memory location directly.
++ */
++
++#define readb(addr) \
++({ \
++ unsigned char __res;\
++ __asm__ __volatile__( \
++ "ldbuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readw(addr) \
++({ \
++ unsigned short __res;\
++ __asm__ __volatile__( \
++ "ldhuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readl(addr) \
++({ \
++ unsigned int __res;\
++ __asm__ __volatile__( \
++ "ldwio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define writeb(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stbio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writew(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "sthio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writel(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stwio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define __raw_readb readb
++#define __raw_readw readw
++#define __raw_readl readl
++#define __raw_writeb writeb
++#define __raw_writew writew
++#define __raw_writel writel
++
++#define mmiowb()
++
++/*
++ * make the short names macros so specific devices
++ * can override them as required
++ */
++
++#define memset_io(addr,c,len) memset((void *)(((unsigned int)(addr)) | 0x80000000),(c),(len))
++#define memcpy_fromio(to,from,len) memcpy((to),(void *)(((unsigned int)(from)) | 0x80000000),(len))
++#define memcpy_toio(to,from,len) memcpy((void *)(((unsigned int)(to)) | 0x80000000),(from),(len))
++
++#define inb(addr) readb(addr)
++#define inw(addr) readw(addr)
++#define inl(addr) readl(addr)
++
++#define outb(x,addr) ((void) writeb(x,addr))
++#define outw(x,addr) ((void) writew(x,addr))
++#define outl(x,addr) ((void) writel(x,addr))
++
++#define inb_p(addr) inb(addr)
++#define inw_p(addr) inw(addr)
++#define inl_p(addr) inl(addr)
++
++#define outb_p(x,addr) outb(x,addr)
++#define outw_p(x,addr) outw(x,addr)
++#define outl_p(x,addr) outl(x,addr)
++
++/* IO macros are needed by userspace programs */
++#ifdef __KERNEL__
++
++extern inline void insb(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)dst;
++ while (count--)
++ *p++ = inb(port);
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _insw(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)dst;
++ while (count--)
++ *p++ = inw(port);
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned destination pointer */
++extern inline void _insl(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)dst;
++ while (count--)
++ *p++ = inl(port);
++}
++
++extern inline void outsb(unsigned long port, void *src, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)src;
++ while (count--)
++ outb( *p++, port );
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _outsw(unsigned long port, void *src, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)src;
++ while (count--)
++ outw( *p++, port );
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned source pointer */
++extern inline void _outsl(unsigned long port, void *src, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)src;
++ while (count--)
++ outl( *p++, port );
++}
++
++
++
++extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
++ int bus, int rdonly)
++{
++ return;
++}
++
++//vic - copied from m68knommu
++
++/* Values for nocacheflag and cmode */
++#define IOMAP_FULL_CACHING 0
++#define IOMAP_NOCACHE_SER 1
++#define IOMAP_NOCACHE_NONSER 2
++#define IOMAP_WRITETHROUGH 3
++
++extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
++extern void __iounmap(void *addr, unsigned long size);
++
++extern inline void *ioremap(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
++}
++extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
++}
++
++extern void iounmap(void *addr);
++
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define dma_cache_inv(_start,_size) dcache_push(_start,_size)
++#define dma_cache_wback(_start,_size) dcache_push(_start,_size)
++#define dma_cache_wback_inv(_start,_size) dcache_push(_start,_size)
++
++/* Pages to physical address... */
++#define page_to_phys(page) page_to_virt(page)
++#define page_to_bus(page) page_to_virt(page)
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#define ioport_map(port, nr) ioremap(port, nr)
++#define ioport_unmap(port) iounmap(port)
++
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++#define xlate_dev_mem_ptr(p) __va(p)
++
++/*
++ * Convert a virtual cached pointer to an uncached pointer
++ */
++#define xlate_dev_kmem_ptr(p) p
++
++#define readsb(p,d,l) insb(p,d,l)
++#define readsw(p,d,l) insw(p,d,l)
++#define readsl(p,d,l) insl(p,d,l)
++#define writesb(p,d,l) outsb(p,d,l)
++#define writesw(p,d,l) outsw(p,d,l)
++#define writesl(p,d,l) outsl(p,d,l)
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#endif /* __KERNEL__ */
++
++#endif /* !(__NIOS2_IO_H) */
++
+diff --git a/include/asm-nios2nommu/ioctl.h b/include/asm-nios2nommu/ioctl.h
+new file mode 100644
+index 0000000..c02a36a
+--- /dev/null
++++ b/include/asm-nios2nommu/ioctl.h
+@@ -0,0 +1,100 @@
++/* $Id: ioctl.h,v 1.1 2006/07/05 06:20:25 gerg Exp $
++ *
++ * linux/ioctl.h for Linux by H.H. Bergman.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_IOCTL_H
++#define _NIOS2_IOCTL_H
++
++/* ioctl command encoding: 32 bits total, command in lower 16 bits,
++ * size of the parameter structure in the lower 14 bits of the
++ * upper 16 bits.
++ * Encoding the size of the parameter structure in the ioctl request
++ * is useful for catching programs compiled with old versions
++ * and to avoid overwriting user space outside the user buffer area.
++ * The highest 2 bits are reserved for indicating the ``access mode''.
++ * NOTE: This limits the max parameter size to 16kB -1 !
++ */
++
++/*
++ * I don't really have any idea about what this should look like, so
++ * for the time being, this is heavily based on the PC definitions.
++ */
++
++/*
++ * The following is for compatibility across the various Linux
++ * platforms. The i386 ioctl numbering scheme doesn't really enforce
++ * a type field. De facto, however, the top 8 bits of the lower 16
++ * bits are indeed used as a type field, so we might just as well make
++ * this explicit here. Please be sure to use the decoding macros
++ * below from now on.
++ */
++#define _IOC_NRBITS 8
++#define _IOC_TYPEBITS 8
++#define _IOC_SIZEBITS 14
++#define _IOC_DIRBITS 2
++
++#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
++#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
++#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
++#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
++
++#define _IOC_NRSHIFT 0
++#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
++#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
++#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
++
++/*
++ * Direction bits.
++ */
++#define _IOC_NONE 0U
++#define _IOC_WRITE 1U
++#define _IOC_READ 2U
++
++#define _IOC(dir,type,nr,size) \
++ (((dir) << _IOC_DIRSHIFT) | \
++ ((type) << _IOC_TYPESHIFT) | \
++ ((nr) << _IOC_NRSHIFT) | \
++ ((size) << _IOC_SIZESHIFT))
++
++/* used to create numbers */
++#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
++#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
++#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
++#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
++
++/* used to decode ioctl numbers.. */
++#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
++#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
++#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
++#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
++
++/* ...and for the drivers/sound files... */
++
++#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
++#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
++#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
++#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
++#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
++
++#endif /* _NIOS2_IOCTL_H */
+diff --git a/include/asm-nios2nommu/ioctls.h b/include/asm-nios2nommu/ioctls.h
+new file mode 100644
+index 0000000..288025c
+--- /dev/null
++++ b/include/asm-nios2nommu/ioctls.h
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2_IOCTLS_H__
++#define __ARCH_NIOS2_IOCTLS_H__
++
++#include <asm/ioctl.h>
++
++/* 0x54 is just a magic number to make these relatively unique ('T') */
++
++#define TCGETS 0x5401
++#define TCSETS 0x5402
++#define TCSETSW 0x5403
++#define TCSETSF 0x5404
++#define TCGETA 0x5405
++#define TCSETA 0x5406
++#define TCSETAW 0x5407
++#define TCSETAF 0x5408
++#define TCSBRK 0x5409
++#define TCXONC 0x540A
++#define TCFLSH 0x540B
++#define TIOCEXCL 0x540C
++#define TIOCNXCL 0x540D
++#define TIOCSCTTY 0x540E
++#define TIOCGPGRP 0x540F
++#define TIOCSPGRP 0x5410
++#define TIOCOUTQ 0x5411
++#define TIOCSTI 0x5412
++#define TIOCGWINSZ 0x5413
++#define TIOCSWINSZ 0x5414
++#define TIOCMGET 0x5415
++#define TIOCMBIS 0x5416
++#define TIOCMBIC 0x5417
++#define TIOCMSET 0x5418
++#define TIOCGSOFTCAR 0x5419
++#define TIOCSSOFTCAR 0x541A
++#define FIONREAD 0x541B
++#define TIOCINQ FIONREAD
++#define TIOCLINUX 0x541C
++#define TIOCCONS 0x541D
++#define TIOCGSERIAL 0x541E
++#define TIOCSSERIAL 0x541F
++#define TIOCPKT 0x5420
++#define FIONBIO 0x5421
++#define TIOCNOTTY 0x5422
++#define TIOCSETD 0x5423
++#define TIOCGETD 0x5424
++#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
++#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
++#define TIOCSBRK 0x5427 /* BSD compatibility */
++#define TIOCCBRK 0x5428 /* BSD compatibility */
++#define TIOCGSID 0x5429 /* Return the session ID of FD */
++#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
++#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
++
++#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
++#define FIOCLEX 0x5451
++#define FIOASYNC 0x5452
++#define TIOCSERCONFIG 0x5453
++#define TIOCSERGWILD 0x5454
++#define TIOCSERSWILD 0x5455
++#define TIOCGLCKTRMIOS 0x5456
++#define TIOCSLCKTRMIOS 0x5457
++#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
++#define TIOCSERGETLSR 0x5459 /* Get line status register */
++#define TIOCSERGETMULTI 0x545A /* Get multiport config */
++#define TIOCSERSETMULTI 0x545B /* Set multiport config */
++
++#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
++#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
++#define FIOQSIZE 0x545E
++
++/* Used for packet mode */
++#define TIOCPKT_DATA 0
++#define TIOCPKT_FLUSHREAD 1
++#define TIOCPKT_FLUSHWRITE 2
++#define TIOCPKT_STOP 4
++#define TIOCPKT_START 8
++#define TIOCPKT_NOSTOP 16
++#define TIOCPKT_DOSTOP 32
++
++#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
++
++#endif /* __ARCH_NIOS2_IOCTLS_H__ */
+diff --git a/include/asm-nios2nommu/ipc.h b/include/asm-nios2nommu/ipc.h
+new file mode 100644
+index 0000000..cb86a31
+--- /dev/null
++++ b/include/asm-nios2nommu/ipc.h
+@@ -0,0 +1,51 @@
++#ifndef __NIOS2_IPC_H__
++#define __NIOS2_IPC_H__
++
++/* Copied from sparc version
++ * These are used to wrap system calls on the Nios.
++ *
++ * See arch/niosnommu/kernel/sys_nios.c for ugly details..
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++struct ipc_kludge {
++ struct msgbuf *msgp;
++ long msgtyp;
++};
++
++#define SEMOP 1
++#define SEMGET 2
++#define SEMCTL 3
++#define MSGSND 11
++#define MSGRCV 12
++#define MSGGET 13
++#define MSGCTL 14
++#define SHMAT 21
++#define SHMDT 22
++#define SHMGET 23
++#define SHMCTL 24
++
++/* Used by the DIPC package, try and avoid reusing it */
++#define DIPC 25
++
++#define IPCCALL(version,op) ((version)<<16 | (op))
++
++#endif
+diff --git a/include/asm-nios2nommu/ipcbuf.h b/include/asm-nios2nommu/ipcbuf.h
+new file mode 100644
+index 0000000..ef59533
+--- /dev/null
++++ b/include/asm-nios2nommu/ipcbuf.h
+@@ -0,0 +1,49 @@
++#ifndef __NIOS2_IPCBUF_H__
++#define __NIOS2_IPCBUF_H__
++
++/* Copied from asm-m68k/ipcbuf.h
++ * The user_ipc_perm structure for Nios architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 32-bit mode_t and seq
++ * - 2 miscellaneous 32-bit values
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++struct ipc64_perm
++{
++ __kernel_key_t key;
++ __kernel_uid32_t uid;
++ __kernel_gid32_t gid;
++ __kernel_uid32_t cuid;
++ __kernel_gid32_t cgid;
++ __kernel_mode_t mode;
++ unsigned short __pad1;
++ unsigned short seq;
++ unsigned short __pad2;
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* __NIOS2_IPCBUF_H__ */
+diff --git a/include/asm-nios2nommu/irq.h b/include/asm-nios2nommu/irq.h
+new file mode 100644
+index 0000000..f0e37a2
+--- /dev/null
++++ b/include/asm-nios2nommu/irq.h
+@@ -0,0 +1,181 @@
++/*
++ * 21Mar2001 1.1 dgt/microtronix
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_IRQ_H_
++#define _NIOS2NOMMU_IRQ_H_
++
++extern void disable_irq(unsigned int);
++extern void enable_irq(unsigned int);
++
++#include <linux/interrupt.h>
++
++#define SYS_IRQS 32
++#define NR_IRQS SYS_IRQS
++
++/*
++ * Interrupt source definitions
++ * General interrupt sources are the level 1-7.
++ * Adding an interrupt service routine for one of these sources
++ * results in the addition of that routine to a chain of routines.
++ * Each one is called in succession. Each individual interrupt
++ * service routine should determine if the device associated with
++ * that routine requires service.
++ */
++
++#define IRQ01 (1) /* level 1 interrupt */
++#define IRQ02 (2) /* level 2 interrupt */
++#define IRQ03 (3) /* level 3 interrupt */
++#define IRQ04 (4) /* level 4 interrupt */
++#define IRQ05 (5) /* level 5 interrupt */
++#define IRQ06 (6) /* level 6 interrupt */
++#define IRQ07 (7) /* level 7 interrupt */
++#define IRQ08 (8) /* level 8 interrupt */
++#define IRQ09 (9) /* level 9 interrupt */
++#define IRQ0A (10) /* level 10 interrupt */
++#define IRQ0B (11) /* level 11 interrupt */
++#define IRQ0C (12) /* level 12 interrupt */
++#define IRQ0D (13) /* level 13 interrupt */
++#define IRQ0E (14) /* level 14 interrupt */
++#define IRQ0F (15) /* level 15 interrupt */
++#define IRQ10 (16) /* level 16 interrupt */
++#define IRQ12 (17) /* level 17 interrupt */
++#define IRQ13 (18) /* level 18 interrupt */
++#define IRQ14 (19) /* level 19 interrupt */
++#define IRQ15 (20) /* level 20 interrupt */
++#define IRQ16 (21) /* level 21 interrupt */
++#define IRQ17 (22) /* level 22 interrupt */
++#define IRQ18 (23) /* level 23 interrupt */
++#define IRQ19 (24) /* level 24 interrupt */
++#define IRQ1A (25) /* level 25 interrupt */
++#define IRQ1B (26) /* level 26 interrupt */
++#define IRQ1C (27) /* level 27 interrupt */
++#define IRQ1D (28) /* level 28 interrupt */
++#define IRQ1E (29) /* level 29 interrupt */
++#define IRQ1F (30) /* level 30 interrupt */
++#define IRQ20 (31) /* level 31 interrupt */
++#define IRQ21 (32) /* level 32 interrupt */
++
++#define IRQMAX IRQ21
++
++/*
++ * "Generic" interrupt sources
++ */
++
++/*
++ * Machine specific interrupt sources.
++ *
++ * Adding an interrupt service routine for a source with this bit
++ * set indicates a special machine specific interrupt source.
++ * The machine specific files define these sources.
++ *
++ * Removed, they are not used by any one.
++ */
++
++/*
++ * various flags for request_irq()
++ */
++#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
++#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
++#define IRQ_FLG_FAST (0x0004)
++#define IRQ_FLG_SLOW (0x0008)
++#define IRQ_FLG_STD (0x8000) /* internally used */
++
++/*
++ * Functions to set and clear the interrupt mask.
++ */
++
++/*
++ * Use a zero to clean the bit.
++ */
++static inline void clrimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "and r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * Use a one to set the bit.
++ */
++static inline void setimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "or r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * This structure is used to chain together the ISRs for a particular
++ * interrupt source (if it supports chaining).
++ */
++typedef struct irq_node {
++ irq_handler_t handler;
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++ struct irq_node *next;
++} irq_node_t;
++
++/*
++ * This function returns a new irq_node_t
++ */
++extern irq_node_t *new_irq_node(void);
++
++/*
++ * This structure has only 4 elements for speed reasons
++ */
++typedef struct irq_hand {
++ irq_handler_t handler;
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++} irq_hand_t;
++
++/* count of spurious interrupts */
++extern volatile unsigned int num_spurious;
++
++#define disable_irq_nosync(i) disable_irq(i)
++
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#endif /* _NIOS2NOMMU_IRQ_H_ */
+diff --git a/include/asm-nios2nommu/irq_node.h b/include/asm-nios2nommu/irq_node.h
+new file mode 100644
+index 0000000..24f9763
+--- /dev/null
++++ b/include/asm-nios2nommu/irq_node.h
+@@ -0,0 +1,36 @@
++#ifndef _NIOS2NOMMU_IRQNODE_H_
++#define _NIOS2NOMMU_IRQNODE_H_
++
++#include <linux/interrupt.h>
++
++/*
++ * This structure is used to chain together the ISRs for a particular
++ * interrupt source (if it supports chaining).
++ */
++typedef struct irq_node {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++ struct irq_node *next;
++} irq_node_t;
++
++/*
++ * This structure has only 4 elements for speed reasons
++ */
++typedef struct irq_handler {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++} irq_handler_t;
++
++/* count of spurious interrupts */
++extern volatile unsigned int num_spurious;
++
++/*
++ * This function returns a new irq_node_t
++ */
++extern irq_node_t *new_irq_node(void);
++
++#endif /* _NIOS2NOMMU_IRQNODE_H_ */
+diff --git a/include/asm-nios2nommu/irq_regs.h b/include/asm-nios2nommu/irq_regs.h
+new file mode 100644
+index 0000000..3dd9c0b
+--- /dev/null
++++ b/include/asm-nios2nommu/irq_regs.h
+@@ -0,0 +1 @@
++#include <asm-generic/irq_regs.h>
+diff --git a/include/asm-nios2nommu/kdebug.h b/include/asm-nios2nommu/kdebug.h
+new file mode 100644
+index 0000000..6ece1b0
+--- /dev/null
++++ b/include/asm-nios2nommu/kdebug.h
+@@ -0,0 +1 @@
++#include <asm-generic/kdebug.h>
+diff --git a/include/asm-nios2nommu/kmap_types.h b/include/asm-nios2nommu/kmap_types.h
+new file mode 100644
+index 0000000..a26b91d
+--- /dev/null
++++ b/include/asm-nios2nommu/kmap_types.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_KMAP_TYPES_H
++#define _ASM_KMAP_TYPES_H
++
++enum km_type {
++ KM_BOUNCE_READ,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ KM_TYPE_NR
++};
++
++#endif
+diff --git a/include/asm-nios2nommu/linkage.h b/include/asm-nios2nommu/linkage.h
+new file mode 100644
+index 0000000..db79297
+--- /dev/null
++++ b/include/asm-nios2nommu/linkage.h
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASM_LINKAGE_H
++#define __ASM_LINKAGE_H
++
++#define __ALIGN .align 3
++#define __ALIGN_STR ".align 3"
++
++#endif
+diff --git a/include/asm-nios2nommu/linux_logo.h b/include/asm-nios2nommu/linux_logo.h
+new file mode 100644
+index 0000000..f9d38e7
+--- /dev/null
++++ b/include/asm-nios2nommu/linux_logo.h
+@@ -0,0 +1,953 @@
++/* $Id: linux_logo.h,v 1.1 2006/07/05 06:20:25 gerg Exp $
++ * include/asm-nios/linux_logo.h: This is a linux logo
++ * to be displayed on boot.
++ *
++ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
++ * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
++ * Copyright (C) 2004 Micrtronix Datacom Ltd.
++ *
++ * You can put anything here, but:
++ * LINUX_LOGO_COLORS has to be less than 224
++ * image size has to be 80x80
++ * values have to start from 0x20
++ * (i.e. RGB(linux_logo_red[0],
++ * linux_logo_green[0],
++ * linux_logo_blue[0]) is color 0x20)
++ * BW image has to be 80x80 as well, with MS bit
++ * on the left
++ * Serial_console ascii image can be any size,
++ * but should contain %s to display the version
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/init.h>
++#include <linux/version.h>
++
++#define linux_logo_banner "Linux/NIOS2 version " UTS_RELEASE
++
++#define __HAVE_ARCH_LINUX_LOGO
++#define __HAVE_ARCH_LINUX_LOGO16
++
++#define LINUX_LOGO_COLORS 221
++
++#ifdef INCLUDE_LINUX_LOGO_DATA
++
++unsigned char linux_logo_red[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79,
++ 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7,
++ 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8,
++ 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6,
++ 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee,
++ 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c,
++ 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e,
++ 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c,
++ 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfe,
++ 0xf6, 0xec, 0xfe, 0xd2, 0xea, 0xf5, 0xf2, 0xf2,
++ 0xe9, 0xee, 0xf6, 0xf2, 0xee, 0xf6, 0xda, 0xd4,
++ 0xfa, 0xca, 0xf2, 0xf6, 0xfe, 0xf2, 0xda, 0xe4,
++ 0xf6, 0xdd, 0xf2, 0xee, 0xfa, 0xf0, 0x12, 0x4a,
++ 0xd6, 0xf2, 0x8e, 0xf2, 0xf6, 0xf6, 0xb5, 0xf1,
++ 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, 0x9a,
++ 0x2e, 0xd2, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62,
++ 0xda, 0xee, 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xe0,
++ 0xae, 0xbe, 0xce, 0xe2, 0xa3, 0x8e, 0x6d, 0x8e,
++ 0x32, 0xaf, 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82,
++ 0x7a, 0x82, 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86,
++ 0x6a, 0x52, 0x59, 0x64, 0x5e,
++};
++
++unsigned char linux_logo_green[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c,
++ 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae,
++ 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8,
++ 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda,
++ 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca,
++ 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76,
++ 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46,
++ 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b,
++ 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfa,
++ 0xea, 0xd7, 0xf6, 0xbc, 0xda, 0xde, 0xda, 0xe6,
++ 0xca, 0xd8, 0xea, 0xe0, 0xcc, 0xf2, 0xce, 0xb2,
++ 0xee, 0xa2, 0xd6, 0xe6, 0xf6, 0xd7, 0xc5, 0xb8,
++ 0xc6, 0xb9, 0xce, 0xde, 0xce, 0xc6, 0x0e, 0x36,
++ 0xae, 0xbe, 0x86, 0xba, 0xbe, 0xe6, 0x8e, 0xc4,
++ 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, 0x7a,
++ 0x20, 0xc6, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46,
++ 0xce, 0xd6, 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa6,
++ 0x87, 0x96, 0xa2, 0xd6, 0x85, 0x7a, 0x6a, 0x6e,
++ 0x22, 0x76, 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53,
++ 0x66, 0x62, 0x42, 0x50, 0x56, 0x42, 0x56, 0x56,
++ 0x56, 0x3e, 0x51, 0x52, 0x56,
++};
++
++unsigned char linux_logo_blue[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08,
++ 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f,
++ 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e,
++ 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c,
++ 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f,
++ 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a,
++ 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e,
++ 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b,
++ 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xea,
++ 0xb6, 0x7c, 0xda, 0x8e, 0xa6, 0x87, 0x66, 0xb6,
++ 0x81, 0x6a, 0xc6, 0x9a, 0x5b, 0xd2, 0xb6, 0x6a,
++ 0xca, 0x45, 0x92, 0xb2, 0xca, 0x52, 0x8a, 0x3e,
++ 0x2e, 0x66, 0x66, 0xae, 0x3e, 0x47, 0x06, 0x0e,
++ 0x52, 0x36, 0x6a, 0x0e, 0x0e, 0xbe, 0x2c, 0x0e,
++ 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, 0x2e,
++ 0x06, 0x9e, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06,
++ 0x9e, 0xae, 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x0a,
++ 0x32, 0x2e, 0x2a, 0xb2, 0x43, 0x48, 0x5f, 0x2e,
++ 0x06, 0x06, 0x07, 0x24, 0x06, 0x32, 0x06, 0x06,
++ 0x46, 0x2e, 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06,
++ 0x3a, 0x22, 0x42, 0x34, 0x42,
++};
++
++unsigned char linux_logo[] __initdata = {
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
++ 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++ 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d,
++ 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24,
++ 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c,
++ 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31,
++ 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34,
++ 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36,
++ 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22,
++ 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25,
++ 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22,
++ 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36,
++ 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36,
++ 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23,
++ 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21,
++ 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b,
++ 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26,
++ 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d,
++ 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32,
++ 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a,
++ 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b,
++ 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37,
++ 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58,
++ 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35,
++ 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
++ 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22,
++ 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67,
++ 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36,
++ 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e,
++ 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73,
++ 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78,
++ 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79,
++ 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c,
++ 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24,
++ 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71,
++ 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36,
++ 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21,
++ 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89,
++ 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36,
++ 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21,
++ 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e,
++ 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23,
++ 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22,
++ 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63,
++ 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c,
++ 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51,
++ 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21,
++ 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97,
++ 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98,
++ 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39,
++ 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32,
++ 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50,
++ 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48,
++ 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23,
++ 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98,
++ 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50,
++ 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b,
++ 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b,
++ 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34,
++ 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52,
++ 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c,
++ 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c,
++ 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b,
++ 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93,
++ 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28,
++ 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99,
++ 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93,
++ 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36,
++ 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x9f, 0x52, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47,
++ 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30,
++ 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c,
++ 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36,
++ 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48,
++ 0x47, 0x9f, 0x48, 0x48, 0x48, 0xa0, 0xa1, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36,
++ 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f,
++ 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36,
++ 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48,
++ 0xa3, 0xa4, 0x48, 0x48, 0x9f, 0xa5, 0xa6, 0x9f,
++ 0x48, 0x48, 0x48, 0xa2, 0xa7, 0x47, 0x48, 0x48,
++ 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23,
++ 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d,
++ 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25,
++ 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0xa8, 0xa1, 0x48, 0x48, 0x9f, 0xa9, 0xa6, 0x9f,
++ 0x48, 0x48, 0xaa, 0xa1, 0xa5, 0x9f, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30,
++ 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32,
++ 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a,
++ 0x36, 0x24, 0x4f, 0x48, 0x52, 0x52, 0x48, 0x48,
++ 0xab, 0xac, 0xa0, 0x48, 0xad, 0xa6, 0xa6, 0x9f,
++ 0x48, 0xa2, 0xa9, 0xa6, 0xa2, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30,
++ 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21,
++ 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25,
++ 0x36, 0x3a, 0x48, 0x48, 0xae, 0xaf, 0x48, 0x48,
++ 0xad, 0xac, 0xa1, 0x9f, 0xa2, 0xa9, 0xa9, 0xa2,
++ 0x48, 0xab, 0x78, 0xa7, 0x48, 0x48, 0x48, 0x48,
++ 0x9f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21,
++ 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36,
++ 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21,
++ 0x23, 0x43, 0x48, 0x48, 0xb0, 0xb1, 0xb2, 0x9f,
++ 0x48, 0xb3, 0xa5, 0xb3, 0xab, 0xa9, 0xa9, 0xb3,
++ 0xb4, 0xa9, 0xb5, 0xb0, 0x48, 0x48, 0xa0, 0xa5,
++ 0xa1, 0xad, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36,
++ 0x2e, 0x9b, 0x48, 0x48, 0x48, 0xb6, 0xb7, 0xa4,
++ 0xa2, 0xa7, 0xb5, 0x78, 0x6f, 0x6f, 0x6e, 0x6f,
++ 0xa9, 0xb5, 0xab, 0x48, 0x9f, 0xab, 0xa9, 0xa1,
++ 0xaa, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36,
++ 0x54, 0x48, 0x48, 0x48, 0x48, 0xa2, 0xa8, 0xa1,
++ 0xa5, 0xa6, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x6f, 0x78, 0xa5, 0xa0, 0xa0, 0x78, 0xa6, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36,
++ 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21,
++ 0x43, 0x48, 0x4b, 0xa2, 0x9f, 0x48, 0xa2, 0xa1,
++ 0xb8, 0x6e, 0x6e, 0xb5, 0x78, 0x6f, 0x78, 0x78,
++ 0x6e, 0x6f, 0x78, 0xb5, 0xa6, 0xa1, 0xa0, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21,
++ 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25,
++ 0x52, 0x48, 0xa3, 0xb1, 0xb6, 0xb3, 0xaa, 0xac,
++ 0x68, 0x68, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x78, 0x6f, 0x6f, 0xb5, 0xa6, 0xb4, 0x48, 0x9f,
++ 0xb4, 0xb4, 0xa2, 0x9f, 0x48, 0x48, 0x4f, 0x21,
++ 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a,
++ 0x47, 0x48, 0xa2, 0xb6, 0xaf, 0xb9, 0xba, 0x68,
++ 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x78,
++ 0x6f, 0x6f, 0xa6, 0x6f, 0xb5, 0xa0, 0xaa, 0xa6,
++ 0xa6, 0xa9, 0xb2, 0xb3, 0x48, 0x48, 0x4c, 0x22,
++ 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39,
++ 0x9b, 0x48, 0x48, 0x48, 0xb0, 0xb0, 0xba, 0xb8,
++ 0x68, 0x68, 0x69, 0x78, 0x6f, 0xb5, 0x6f, 0xb5,
++ 0x78, 0x78, 0x78, 0x78, 0x78, 0xa5, 0xbb, 0xa9,
++ 0xa5, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23,
++ 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31,
++ 0x9b, 0x48, 0x48, 0x48, 0x48, 0x9f, 0xac, 0x68,
++ 0xbc, 0x6e, 0x6e, 0x6e, 0xb5, 0x6f, 0x6e, 0x6f,
++ 0x6f, 0x78, 0x78, 0xb5, 0xb5, 0xa5, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22,
++ 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d,
++ 0x9b, 0x48, 0x48, 0xb0, 0xaa, 0xb3, 0xbd, 0xb8,
++ 0xb8, 0x68, 0x6e, 0x6e, 0xb5, 0x6f, 0x78, 0x6e,
++ 0x78, 0x6f, 0x78, 0x78, 0xb5, 0xa9, 0xa2, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x24, 0x27, 0xbe, 0x24, 0x25, 0x28, 0x21, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25,
++ 0x39, 0x4d, 0xbf, 0x84, 0x81, 0x57, 0x21, 0x39,
++ 0x52, 0x48, 0x48, 0x62, 0xb1, 0xc0, 0xc1, 0xc1,
++ 0xb8, 0xb8, 0x68, 0xbc, 0x6e, 0x6e, 0x6e, 0x78,
++ 0x78, 0x78, 0x78, 0x6e, 0x78, 0xa9, 0xa0, 0xab,
++ 0xb3, 0xa2, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28,
++ 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30,
++ 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30,
++ 0x2d, 0xc2, 0x7a, 0xc3, 0xc4, 0xc4, 0x7f, 0x22,
++ 0x51, 0x52, 0x48, 0x48, 0xb0, 0xaa, 0xa8, 0xbd,
++ 0x68, 0xb8, 0xb8, 0x68, 0x68, 0x6e, 0x6e, 0x6f,
++ 0x6e, 0x6e, 0xb5, 0x6e, 0x78, 0xab, 0xab, 0xb5,
++ 0x78, 0xa6, 0xb3, 0xc5, 0xac, 0xac, 0xc6, 0x61,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32,
++ 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31,
++ 0x4d, 0x91, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0x5a,
++ 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0xb0, 0x64,
++ 0xc1, 0xb8, 0xb8, 0xb8, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6f, 0x71, 0x6f, 0x6f, 0xa6, 0xa0, 0x9f, 0xb4,
++ 0xb4, 0xa0, 0xa1, 0xb7, 0xc7, 0x69, 0x66, 0xc8,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25,
++ 0x83, 0xc9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a,
++ 0x60, 0x85, 0xca, 0xcb, 0xc4, 0xc4, 0xc4, 0x82,
++ 0x86, 0x36, 0x32, 0x3f, 0xa2, 0xa4, 0xa8, 0xa9,
++ 0xb8, 0xb8, 0xb8, 0xb8, 0x68, 0x6e, 0x6e, 0x6e,
++ 0x6e, 0x71, 0x6f, 0x71, 0xa6, 0xb4, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0xcc, 0xc3, 0xc7, 0xcd, 0xce,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57,
++ 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x23, 0x30, 0x31, 0xcf, 0x91, 0x7e, 0x90, 0x90,
++ 0x8b, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0x5d, 0xd0, 0x36, 0x24, 0xd1, 0xb1, 0xaf, 0xaa,
++ 0xba, 0xb8, 0x68, 0x68, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6e, 0x6f, 0x6e, 0x78, 0xa1, 0xa9, 0xa1, 0xb0,
++ 0x9f, 0x9b, 0x99, 0xcc, 0x64, 0x5c, 0x8b, 0xd0,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d,
++ 0x82, 0x5c, 0xd2, 0x2a, 0x23, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x24, 0x2b, 0xcf, 0x8b, 0x5b, 0x76, 0x5b, 0x5b,
++ 0x7b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc7, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48,
++ 0xa2, 0xa8, 0xb7, 0xc1, 0xb8, 0x68, 0x68, 0xbc,
++ 0x68, 0x6e, 0xb5, 0xb4, 0xb4, 0xab, 0xb5, 0xa1,
++ 0xb0, 0x4f, 0x3f, 0xd3, 0x7b, 0x7b, 0x85, 0x80,
++ 0xbe, 0x36, 0x36, 0x36, 0x21, 0xd4, 0x7e, 0x7b,
++ 0x64, 0x64, 0xd5, 0x35, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x31, 0xd6, 0x5b, 0x64, 0xc3, 0xc3, 0xcb,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x66, 0xd7, 0x36, 0x36, 0x36, 0x2c, 0x4b,
++ 0xd8, 0xd9, 0xb3, 0xa8, 0xbd, 0xbd, 0xbd, 0xbd,
++ 0xa9, 0xab, 0xb3, 0xa5, 0xa2, 0x9f, 0xa2, 0xa1,
++ 0x6a, 0x9a, 0x3f, 0xda, 0x76, 0x76, 0x7a, 0x63,
++ 0xdb, 0xdc, 0x86, 0xdc, 0xdd, 0x90, 0x5b, 0x64,
++ 0xc3, 0xc3, 0xde, 0x2d, 0x27, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc7, 0x83, 0xce, 0x36, 0x36, 0x36, 0x30,
++ 0xb1, 0xd9, 0x48, 0xa1, 0xb2, 0xb0, 0xb0, 0xb3,
++ 0xa2, 0x48, 0xa7, 0xbd, 0xa9, 0xa2, 0x48, 0x9f,
++ 0xaa, 0x9a, 0x3f, 0xb1, 0x5b, 0x7b, 0xdf, 0x85,
++ 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xc3, 0xc4,
++ 0xc4, 0xcb, 0x5d, 0xd5, 0x39, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe0, 0xdf, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x88, 0x36, 0x36, 0x36, 0x36,
++ 0x2d, 0x9b, 0x48, 0xb9, 0xaf, 0xa2, 0xa2, 0xb9,
++ 0xa8, 0x9f, 0x48, 0xa7, 0xb7, 0xd9, 0x48, 0x48,
++ 0x9b, 0x45, 0x3f, 0xe1, 0x6d, 0x7b, 0xca, 0xdf,
++ 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc3, 0xe2, 0x37, 0x35, 0x26, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2e, 0xe0, 0x7a, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x72, 0x73, 0x36, 0x36, 0x36,
++ 0x24, 0x52, 0x48, 0xa3, 0xaf, 0x9f, 0x48, 0xb6,
++ 0xaf, 0xa2, 0x48, 0x9f, 0xe3, 0xd8, 0x48, 0x48,
++ 0x48, 0x46, 0x42, 0xd6, 0x7a, 0x7b, 0x64, 0x7b,
++ 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xc3, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0x64, 0xe2, 0x4d, 0x2c, 0x27,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x8b, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc7, 0x89, 0xbe, 0x36, 0x36,
++ 0x32, 0x47, 0x48, 0x4f, 0xa0, 0x48, 0x48, 0xe3,
++ 0x92, 0x9f, 0x48, 0x9f, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xc3, 0xcb,
++ 0xc3, 0x64, 0x64, 0xc3, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x5d, 0xe5, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x85, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x57, 0x27, 0x4d,
++ 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x99, 0x34, 0xbe, 0xdb, 0x7a, 0x7b, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xe4,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe4, 0x85, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc7, 0x5f, 0x92, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44,
++ 0x35, 0x36, 0xce, 0xdd, 0x7a, 0x7b, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xc3, 0xe1,
++ 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x30, 0x2f, 0xd6, 0x8b, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x89, 0x45,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25,
++ 0x36, 0x36, 0x61, 0xdb, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0xdf, 0xe5,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xe6, 0x63, 0xdf, 0xc3, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x72, 0x81, 0xe7,
++ 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36,
++ 0x36, 0x36, 0xe8, 0x8f, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc3, 0xca, 0x8b, 0xcf, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x96, 0x75, 0xca, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0x81, 0xdb,
++ 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b,
++ 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x73, 0xdb, 0x7a, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x64, 0x76, 0x7a, 0x91, 0xd5, 0x31, 0x30,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x39, 0x97, 0x75, 0xdf, 0x7b, 0x64, 0xc3, 0xc3,
++ 0xcb, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x7b, 0x7a, 0xe9,
++ 0xea, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30,
++ 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xdd, 0x8b, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x64, 0x64,
++ 0x76, 0x85, 0xe0, 0xd5, 0x34, 0x2b, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xeb, 0x63, 0x7e, 0x7a, 0x6d, 0xdf, 0x5b,
++ 0x76, 0x7b, 0x64, 0x64, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x76, 0x85, 0xdb,
++ 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xec, 0xdd, 0x75, 0x76, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0xc3, 0x64, 0x76, 0xdf, 0x8b,
++ 0xd6, 0xd5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x31, 0xed, 0xeb, 0xdd, 0x74, 0x63, 0x90,
++ 0x7e, 0x75, 0x8b, 0x6d, 0xdf, 0x76, 0x64, 0xc3,
++ 0xcb, 0xcb, 0xcb, 0xcb, 0x64, 0x7a, 0x84, 0xee,
++ 0x79, 0xbe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xee, 0x63, 0x6d, 0x7b, 0x64,
++ 0xcb, 0xc3, 0x64, 0x7b, 0xdf, 0x75, 0x63, 0x96,
++ 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x27, 0x35, 0x2d, 0x41, 0xd5, 0xe7, 0x8f,
++ 0xdb, 0xdd, 0xe9, 0x74, 0x84, 0x90, 0x85, 0x6d,
++ 0x5b, 0x7b, 0x7b, 0xca, 0x6d, 0x90, 0xdb, 0xef,
++ 0xec, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30,
++ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36,
++ 0x36, 0x21, 0xd4, 0x80, 0xe9, 0x7e, 0x6d, 0x76,
++ 0xca, 0x76, 0x6d, 0x85, 0x63, 0xdb, 0xd5, 0x34,
++ 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f,
++ 0x41, 0xf0, 0xf1, 0x6c, 0x80, 0xee, 0xdb, 0x74,
++ 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xef, 0x79,
++ 0xe8, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d,
++ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38,
++ 0x4d, 0x37, 0xf2, 0xf3, 0x8f, 0x74, 0x63, 0x7e,
++ 0x75, 0x7e, 0x63, 0xe9, 0x88, 0xe6, 0x31, 0x2a,
++ 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30,
++ 0x33, 0x39, 0x2e, 0x51, 0x41, 0xd2, 0x6c, 0xf3,
++ 0x80, 0xee, 0xee, 0xee, 0xf4, 0xf3, 0xd7, 0xf5,
++ 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27,
++ 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a,
++ 0x2b, 0x34, 0xf6, 0xec, 0xf7, 0x8f, 0xdd, 0xe9,
++ 0xe9, 0xdd, 0xee, 0x6c, 0x41, 0x39, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22,
++ 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41,
++ 0xf8, 0xd7, 0x79, 0x79, 0x79, 0xec, 0xf9, 0x51,
++ 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22,
++ 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23,
++ 0x24, 0x2a, 0x31, 0xfa, 0xea, 0x79, 0xf3, 0x80,
++ 0xf7, 0xdc, 0xfb, 0x2f, 0x35, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b,
++ 0x31, 0x2f, 0xf6, 0xfa, 0xfa, 0x2f, 0x2e, 0x33,
++ 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x27, 0x35, 0x34, 0xfa, 0xfa, 0xfa,
++ 0xfc, 0xf6, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28,
++ 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35,
++ 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24,
++ 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++};
++
++unsigned char linux_logo16[1];
++
++#endif /* INCLUDE_LINUX_LOGO_DATA */
++
++#include <linux/linux_logo.h>
++
+diff --git a/include/asm-nios2nommu/local.h b/include/asm-nios2nommu/local.h
+new file mode 100644
+index 0000000..5ed7d1c
+--- /dev/null
++++ b/include/asm-nios2nommu/local.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_LOCAL_H
++#define __NIOS2NOMMU_LOCAL_H
++
++#include <asm-generic/local.h>
++
++#endif /* __NIOS2NOMMU_LOCAL_H */
+diff --git a/include/asm-nios2nommu/mc146818rtc.h b/include/asm-nios2nommu/mc146818rtc.h
+new file mode 100644
+index 0000000..3492fc0
+--- /dev/null
++++ b/include/asm-nios2nommu/mc146818rtc.h
+@@ -0,0 +1,29 @@
++/*
++ * Machine dependent access functions for RTC registers.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MC146818RTC_H
++#define _NIOS2_MC146818RTC_H
++
++/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
++
++#endif /* _NIOS2_MC146818RTC_H */
+diff --git a/include/asm-nios2nommu/mman.h b/include/asm-nios2nommu/mman.h
+new file mode 100644
+index 0000000..516ab26
+--- /dev/null
++++ b/include/asm-nios2nommu/mman.h
+@@ -0,0 +1,68 @@
++/*
++ * Copied from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_MMAN_H__
++#define __NIOS2_MMAN_H__
++
++#define PROT_READ 0x1 /* page can be read */
++#define PROT_WRITE 0x2 /* page can be written */
++#define PROT_EXEC 0x4 /* page can be executed */
++#define PROT_SEM 0x8 /* page may be used for atomic ops */
++#define PROT_NONE 0x0 /* page can not be accessed */
++#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
++#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
++
++#define MAP_SHARED 0x01 /* Share changes */
++#define MAP_PRIVATE 0x02 /* Changes are private */
++#define MAP_TYPE 0x0f /* Mask for type of mapping */
++#define MAP_FIXED 0x10 /* Interpret addr exactly */
++#define MAP_ANONYMOUS 0x20 /* don't use a file */
++
++#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
++#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
++#define MAP_LOCKED 0x2000 /* pages are locked */
++#define MAP_NORESERVE 0x4000 /* don't check for reservations */
++#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++#define MAP_NONBLOCK 0x10000 /* do not block on IO */
++
++#define MS_ASYNC 1 /* sync memory asynchronously */
++#define MS_INVALIDATE 2 /* invalidate the caches */
++#define MS_SYNC 4 /* synchronous memory sync */
++
++#define MCL_CURRENT 1 /* lock all current mappings */
++#define MCL_FUTURE 2 /* lock all future mappings */
++
++#define MADV_NORMAL 0x0 /* default page-in behavior */
++#define MADV_RANDOM 0x1 /* page-in minimum required */
++#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
++#define MADV_WILLNEED 0x3 /* pre-fault pages */
++#define MADV_DONTNEED 0x4 /* discard these pages */
++
++/* compatibility flags */
++#define MAP_ANON MAP_ANONYMOUS
++#define MAP_FILE 0
++
++#endif /* __NIOS2_MMAN_H__ */
++
+diff --git a/include/asm-nios2nommu/mmu.h b/include/asm-nios2nommu/mmu.h
+new file mode 100644
+index 0000000..b6e579d
+--- /dev/null
++++ b/include/asm-nios2nommu/mmu.h
+@@ -0,0 +1,36 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_H
++#define __NIOS2NOMMU_MMU_H
++
++/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
++
++typedef struct {
++ struct vm_list_struct *vmlist;
++ unsigned long end_brk;
++} mm_context_t;
++
++#endif /* __NIOS2NOMMU_MMU_H */
+diff --git a/include/asm-nios2nommu/mmu_context.h b/include/asm-nios2nommu/mmu_context.h
+new file mode 100644
+index 0000000..795cd09
+--- /dev/null
++++ b/include/asm-nios2nommu/mmu_context.h
+@@ -0,0 +1,57 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_CONTEXT_H
++#define __NIOS2NOMMU_MMU_CONTEXT_H
++
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++}
++
++extern inline int
++init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++ // mm->context = virt_to_phys(mm->pgd);
++ return(0);
++}
++
++#define destroy_context(mm) do { } while(0)
++
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
++{
++}
++
++#define deactivate_mm(tsk,mm) do { } while (0)
++
++extern inline void activate_mm(struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++}
++
++#endif
+diff --git a/include/asm-nios2nommu/module.h b/include/asm-nios2nommu/module.h
+new file mode 100644
+index 0000000..864f335
+--- /dev/null
++++ b/include/asm-nios2nommu/module.h
+@@ -0,0 +1,36 @@
++#ifndef _NIOS2_MODULE_H
++#define _NIOS2_MODULE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/module.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct mod_arch_specific
++{
++};
++
++#define Elf_Shdr Elf32_Shdr
++#define Elf_Sym Elf32_Sym
++#define Elf_Ehdr Elf32_Ehdr
++
++#endif /* _NIOS_MODULE_H */
+diff --git a/include/asm-nios2nommu/msgbuf.h b/include/asm-nios2nommu/msgbuf.h
+new file mode 100644
+index 0000000..4d090f7
+--- /dev/null
++++ b/include/asm-nios2nommu/msgbuf.h
+@@ -0,0 +1,56 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MSGBUF_H
++#define _NIOS2_MSGBUF_H
++
++/*
++ * The msqid64_ds structure for nios2 architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct msqid64_ds {
++ struct ipc64_perm msg_perm;
++ __kernel_time_t msg_stime; /* last msgsnd time */
++ unsigned long __unused1;
++ __kernel_time_t msg_rtime; /* last msgrcv time */
++ unsigned long __unused2;
++ __kernel_time_t msg_ctime; /* last change time */
++ unsigned long __unused3;
++ unsigned long msg_cbytes; /* current number of bytes on queue */
++ unsigned long msg_qnum; /* number of messages in queue */
++ unsigned long msg_qbytes; /* max number of bytes on queue */
++ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
++ __kernel_pid_t msg_lrpid; /* last receive pid */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#endif /* _NIOS2_MSGBUF_H */
++
+diff --git a/include/asm-nios2nommu/mutex.h b/include/asm-nios2nommu/mutex.h
+new file mode 100644
+index 0000000..458c1f7
+--- /dev/null
++++ b/include/asm-nios2nommu/mutex.h
+@@ -0,0 +1,9 @@
++/*
++ * Pull in the generic implementation for the mutex fastpath.
++ *
++ * TODO: implement optimized primitives instead, or leave the generic
++ * implementation in place, or pick the atomic_xchg() based generic
++ * implementation. (see asm-generic/mutex-xchg.h for details)
++ */
++
++#include <asm-generic/mutex-dec.h>
+diff --git a/include/asm-nios2nommu/namei.h b/include/asm-nios2nommu/namei.h
+new file mode 100644
+index 0000000..d925c4e
+--- /dev/null
++++ b/include/asm-nios2nommu/namei.h
+@@ -0,0 +1,36 @@
++/*
++ * linux/include/asm-nios/namei.h
++ * Moved from m68k version
++ * Included from linux/fs/namei.c
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_NAMEI_H
++#define __NIOS2_NAMEI_H
++
++/* This dummy routine maybe changed to something useful
++ * for /usr/gnemul/ emulation stuff.
++ * Look at asm-sparc/namei.h for details.
++ */
++
++#define __emul_prefix() NULL
++
++#endif
+diff --git a/include/asm-nios2nommu/ndma.h b/include/asm-nios2nommu/ndma.h
+new file mode 100644
+index 0000000..6b4604d
+--- /dev/null
++++ b/include/asm-nios2nommu/ndma.h
+@@ -0,0 +1,64 @@
++#ifndef __NDMA_H__
++ #define __NDMA_H__
++
++ #ifndef __ASSEMBLY__
++
++// DMA Registers
++typedef volatile struct
++{
++ int np_dmastatus; // status register
++ int np_dmareadaddress; // read address
++ int np_dmawriteaddress; // write address
++ int np_dmalength; // length in bytes
++ int np_dmareserved1; // reserved
++ int np_dmareserved2; // reserved
++ int np_dmacontrol; // control register
++ int np_dmareserved3; // control register alternate
++} np_dma;
++
++// DMA Register Bits
++enum
++{
++ np_dmacontrol_byte_bit = 0, // Byte transaction
++ np_dmacontrol_hw_bit = 1, // Half-word transaction
++ np_dmacontrol_word_bit = 2, // Word transaction
++ np_dmacontrol_go_bit = 3, // enable execution
++ np_dmacontrol_i_en_bit = 4, // enable interrupt
++ np_dmacontrol_reen_bit = 5, // Enable read end-of-packet
++ np_dmacontrol_ween_bit = 6, // Enable write end-of-packet
++ np_dmacontrol_leen_bit = 7, // Enable length=0 transaction end
++ np_dmacontrol_rcon_bit = 8, // Read from a fixed address
++ np_dmacontrol_wcon_bit = 9, // Write to a fixed address
++ np_dmacontrol_doubleword_bit = 10, // Double-word transaction
++ np_dmacontrol_quadword_bit = 11, // Quad-word transaction
++
++ np_dmastatus_done_bit = 0, // 1 when done. Status write clears.
++ np_dmastatus_busy_bit = 1, // 1 when busy.
++ np_dmastatus_reop_bit = 2, // read-eop received
++ np_dmastatus_weop_bit = 3, // write-eop received
++ np_dmastatus_len_bit = 4, // requested length transacted
++
++ np_dmacontrol_byte_mask = (1 << 0), // Byte transaction
++ np_dmacontrol_hw_mask = (1 << 1), // Half-word transaction
++ np_dmacontrol_word_mask = (1 << 2), // Word transaction
++ np_dmacontrol_go_mask = (1 << 3), // enable execution
++ np_dmacontrol_i_en_mask = (1 << 4), // enable interrupt
++ np_dmacontrol_reen_mask = (1 << 5), // Enable read end-of-packet
++ np_dmacontrol_ween_mask = (1 << 6), // Enable write end-of-packet
++ np_dmacontrol_leen_mask = (1 << 7), // Enable length=0 transaction end
++ np_dmacontrol_rcon_mask = (1 << 8), // Read from a fixed address
++ np_dmacontrol_wcon_mask = (1 << 9), // Write to a fixed address
++ np_dmacontrol_doubleword_mask = (1 << 10), // Double-word transaction
++ np_dmacontrol_quadword_mask = (1 << 11), // Quad-word transaction
++
++ np_dmastatus_done_mask = (1 << 0), // 1 when done. Status write clears.
++ np_dmastatus_busy_mask = (1 << 1), // 1 when busy.
++ np_dmastatus_reop_mask = (1 << 2), // read-eop received
++ np_dmastatus_weop_mask = (1 << 3), // write-eop received
++ np_dmastatus_len_mask = (1 << 4), // requested length transacted
++};
++
++ #endif /* __ASSEMBLY__ */
++
++#endif
++/* End of File */
+diff --git a/include/asm-nios2nommu/nios.h b/include/asm-nios2nommu/nios.h
+new file mode 100644
+index 0000000..df17672
+--- /dev/null
++++ b/include/asm-nios2nommu/nios.h
+@@ -0,0 +1,7 @@
++#ifndef __NIOS_H__
++#define __NIOS_H__
++
++#include <nios2_system.h>
++
++#endif
++
+diff --git a/include/asm-nios2nommu/page.h b/include/asm-nios2nommu/page.h
+new file mode 100644
+index 0000000..764e73c
+--- /dev/null
++++ b/include/asm-nios2nommu/page.h
+@@ -0,0 +1,124 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_PAGE_H
++#define _NIOS2_PAGE_H
++
++/* copied from m68knommu arch */
++
++/* PAGE_SHIFT determines the page size */
++
++#define PAGE_SHIFT (12)
++#define PAGE_SIZE (1UL << PAGE_SHIFT)
++#define PAGE_MASK (~(PAGE_SIZE-1))
++
++#ifdef __KERNEL__
++
++#include <asm/setup.h>
++
++#if PAGE_SHIFT < 13
++#define THREAD_SIZE (8192)
++#else
++#define THREAD_SIZE PAGE_SIZE
++#endif
++
++#ifndef __ASSEMBLY__
++
++#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
++#define free_user_page(page, addr) free_page(addr)
++
++#define clear_page(page) memset((page), 0, PAGE_SIZE)
++#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
++
++#define clear_user_page(page, vaddr, pg) clear_page(page)
++#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
++
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef struct { unsigned long pte; } pte_t;
++typedef struct { unsigned long pmd[16]; } pmd_t;
++typedef struct { unsigned long pgd; } pgd_t;
++typedef struct { unsigned long pgprot; } pgprot_t;
++
++#define pte_val(x) ((x).pte)
++#define pmd_val(x) ((&x)->pmd[0])
++#define pgd_val(x) ((x).pgd)
++#define pgprot_val(x) ((x).pgprot)
++
++#define __pte(x) ((pte_t) { (x) } )
++#define __pmd(x) ((pmd_t) { (x) } )
++#define __pgd(x) ((pgd_t) { (x) } )
++#define __pgprot(x) ((pgprot_t) { (x) } )
++
++/* to align the pointer to the (next) page boundary */
++#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
++
++extern unsigned long memory_start;
++extern unsigned long memory_end;
++
++#endif /* !__ASSEMBLY__ */
++#include <asm/nios.h>
++#define PAGE_OFFSET ((int)(nasys_program_mem))
++
++#ifndef __ASSEMBLY__
++
++#define __pa(vaddr) virt_to_phys((void *)(vaddr))
++#define __va(paddr) phys_to_virt((unsigned long)(paddr))
++
++#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
++
++#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
++#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
++
++#define virt_to_page(addr) ((void*) addr < (void*) memory_end ? mem_map + \
++ (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) : 0UL)
++#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
++#define VALID_PAGE(page) (((page) - mem_map) < max_mapnr)
++
++#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
++#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
++#define pfn_valid(pfn) ((pfn) < max_mapnr)
++
++#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
++ ((void *)(kaddr) < (void *)memory_end))
++
++#ifdef CONFIG_NO_KERNEL_MSG
++#define BUG_PRINT()
++#else
++#define BUG_PRINT() printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__)
++#endif
++
++#ifdef na_cpu_oci_core
++#define BUG_PANIC() asm volatile ("break") /* drop to debugger */
++#else
++// #define BUG_PANIC() while(1)
++#define BUG_PANIC() panic("BUG!")
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#include <asm-generic/page.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_PAGE_H */
+diff --git a/include/asm-nios2nommu/param.h b/include/asm-nios2nommu/param.h
+new file mode 100644
+index 0000000..e75a355
+--- /dev/null
++++ b/include/asm-nios2nommu/param.h
+@@ -0,0 +1,49 @@
++#ifndef _NIOS_PARAM_H
++#define _NIOS_PARAM_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/param.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifndef HZ
++#define HZ 100
++#endif
++
++#ifdef __KERNEL__
++#define USER_HZ HZ
++#define CLOCKS_PER_SEC (USER_HZ)
++#endif
++
++#define EXEC_PAGESIZE 4096
++
++#ifndef NGROUPS
++#define NGROUPS 32
++#endif
++
++#ifndef NOGROUP
++#define NOGROUP (-1)
++#endif
++
++#define MAXHOSTNAMELEN 64 /* max length of hostname */
++
++#endif
+diff --git a/include/asm-nios2nommu/pci.h b/include/asm-nios2nommu/pci.h
+new file mode 100644
+index 0000000..be3b3b2
+--- /dev/null
++++ b/include/asm-nios2nommu/pci.h
+@@ -0,0 +1,126 @@
++#ifndef __ASM_SH_PCI_H
++#define __ASM_SH_PCI_H
++
++#ifdef __KERNEL__
++
++#include <linux/dma-mapping.h>
++
++/* Can be used to override the logic in pci_scan_bus for skipping
++ already-configured bus numbers - to be used for buggy BIOSes
++ or architectures with incomplete PCI setup by the loader */
++
++#define pcibios_assign_all_busses() 1
++#define pcibios_scan_all_fns(a, b) 0
++
++/*
++ * A board can define one or more PCI channels that represent built-in (or
++ * external) PCI controllers.
++ */
++struct pci_channel {
++ struct pci_ops *pci_ops;
++ struct resource *io_resource;
++ struct resource *mem_resource;
++ int first_devfn;
++ int last_devfn;
++};
++
++/*
++ * Each board initializes this array and terminates it with a NULL entry.
++ */
++extern struct pci_channel board_pci_channels[];
++
++#define PCIBIOS_MIN_IO board_pci_channels->io_resource->start
++#define PCIBIOS_MIN_MEM board_pci_channels->mem_resource->start
++
++struct pci_dev;
++
++extern void pcibios_set_master(struct pci_dev *dev);
++
++static inline void pcibios_penalize_isa_irq(int irq, int active)
++{
++ /* We don't do dynamic PCI IRQ allocation */
++}
++
++/* Dynamic DMA mapping stuff.
++ * SuperH has everything mapped statically like x86.
++ */
++
++/* The PCI address space does equal the physical memory
++ * address space. The networking and block device layers use
++ * this boolean for bounce buffer decisions.
++ */
++#define PCI_DMA_BUS_IS_PHYS (1)
++
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <asm/scatterlist.h>
++#include <linux/string.h>
++#include <asm/io.h>
++
++/* pci_unmap_{single,page} being a nop depends upon the
++ * configuration.
++ */
++#ifdef CONFIG_SH_PCIDMA_NONCOHERENT
++#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
++ dma_addr_t ADDR_NAME;
++#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
++ __u32 LEN_NAME;
++#define pci_unmap_addr(PTR, ADDR_NAME) \
++ ((PTR)->ADDR_NAME)
++#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
++ (((PTR)->ADDR_NAME) = (VAL))
++#define pci_unmap_len(PTR, LEN_NAME) \
++ ((PTR)->LEN_NAME)
++#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
++ (((PTR)->LEN_NAME) = (VAL))
++#else
++#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
++#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
++#define pci_unmap_addr(PTR, ADDR_NAME) (0)
++#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
++#define pci_unmap_len(PTR, LEN_NAME) (0)
++#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
++#endif
++
++/* Not supporting more than 32-bit PCI bus addresses now, but
++ * must satisfy references to this function. Change if needed.
++ */
++#define pci_dac_dma_supported(pci_dev, mask) (0)
++
++/* These macros should be used after a pci_map_sg call has been done
++ * to get bus addresses of each of the SG entries and their lengths.
++ * You should only work with the number of sg entries pci_map_sg
++ * returns, or alternatively stop on the first sg_dma_len(sg) which
++ * is 0.
++ */
++#define sg_dma_address(sg) (virt_to_bus((sg)->dma_address))
++#define sg_dma_len(sg) ((sg)->length)
++
++#ifdef CONFIG_PCI
++static inline void pci_dma_burst_advice(struct pci_dev *pdev,
++ enum pci_dma_burst_strategy *strat,
++ unsigned long *strategy_parameter)
++{
++ *strat = PCI_DMA_BURST_INFINITY;
++ *strategy_parameter = ~0UL;
++}
++#endif
++
++/* Board-specific fixup routines. */
++extern void pcibios_fixup(void);
++extern void pcibios_fixup_irqs(void);
++
++#ifdef CONFIG_PCI_AUTO
++extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
++#endif
++
++#endif /* __KERNEL__ */
++
++/* generic pci stuff */
++#include <asm-generic/pci.h>
++
++/* generic DMA-mapping stuff */
++#include <asm-generic/pci-dma-compat.h>
++
++#endif /* __ASM_SH_PCI_H */
++
+diff --git a/include/asm-nios2nommu/percpu.h b/include/asm-nios2nommu/percpu.h
+new file mode 100644
+index 0000000..cd6d4a3
+--- /dev/null
++++ b/include/asm-nios2nommu/percpu.h
+@@ -0,0 +1,30 @@
++#ifndef __ARCH_NIOS2NOMMU_PERCPU__
++#define __ARCH_NIOS2NOMMU_PERCPU__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/percpu.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/percpu.h>
++
++#endif /* __ARCH_NIOS2NOMMU_PERCPU__ */
+diff --git a/include/asm-nios2nommu/pgalloc.h b/include/asm-nios2nommu/pgalloc.h
+new file mode 100644
+index 0000000..a997ada
+--- /dev/null
++++ b/include/asm-nios2nommu/pgalloc.h
+@@ -0,0 +1,32 @@
++#ifndef _NIOS2NOMMU_PGALLOC_H
++#define _NIOS2NOMMU_PGALLOC_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgalloc.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/setup.h>
++
++#define check_pgt_cache() do { } while (0)
++
++#endif /* _NIOS2NOMMU_PGALLOC_H */
+diff --git a/include/asm-nios2nommu/pgtable.h b/include/asm-nios2nommu/pgtable.h
+new file mode 100644
+index 0000000..4124a33
+--- /dev/null
++++ b/include/asm-nios2nommu/pgtable.h
+@@ -0,0 +1,112 @@
++#ifndef _NIOS_PGTABLE_H
++#define _NIOS_PGTABLE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgtable.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm-generic/4level-fixup.h>
++
++//vic - this bit copied from m68knommu version
++#include <asm/setup.h>
++#include <asm/io.h>
++#include <linux/sched.h>
++
++typedef pte_t *pte_addr_t;
++
++#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
++#define pgd_none(pgd) (0)
++#define pgd_bad(pgd) (0)
++#define pgd_clear(pgdp)
++#define kern_addr_valid(addr) (1)
++#define pmd_offset(a, b) ((void *)0)
++
++#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
++//vic - this bit copied from m68knommu version
++
++extern void paging_init(void);
++#define swapper_pg_dir ((pgd_t *) 0)
++
++#define __swp_type(x) (0)
++#define __swp_offset(x) (0)
++#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
++#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
++#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
++
++static inline int pte_file(pte_t pte) { return 0; }
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++#define ZERO_PAGE(vaddr) (virt_to_page(0))
++
++extern unsigned int kobjsize(const void *objp);
++extern int is_in_rom(unsigned long);
++
++/*
++ * No page table caches to initialise
++ */
++#define pgtable_cache_init() do { } while (0)
++
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
++ remap_pfn_range(vma, vaddr, pfn, size, prot)
++
++extern inline void flush_cache_mm(struct mm_struct *mm)
++{
++}
++
++extern inline void flush_cache_range(struct mm_struct *mm,
++ unsigned long start,
++ unsigned long end)
++{
++}
++
++/* Push the page at kernel virtual address and clear the icache */
++extern inline void flush_page_to_ram (unsigned long address)
++{
++}
++
++/* Push n pages at kernel virtual address and clear the icache */
++extern inline void flush_pages_to_ram (unsigned long address, int n)
++{
++}
++
++/*
++ * All 32bit addresses are effectively valid for vmalloc...
++ * Sort of meaningless for non-VM targets.
++ */
++#define VMALLOC_START 0
++#define VMALLOC_END 0xffffffff
++
++#define arch_enter_lazy_mmu_mode() do {} while (0)
++#define arch_leave_lazy_mmu_mode() do {} while (0)
++#define arch_flush_lazy_mmu_mode() do {} while (0)
++#define arch_enter_lazy_cpu_mode() do {} while (0)
++#define arch_leave_lazy_cpu_mode() do {} while (0)
++#define arch_flush_lazy_cpu_mode() do {} while (0)
++
++#endif /* _NIOS_PGTABLE_H */
+diff --git a/include/asm-nios2nommu/pio_struct.h b/include/asm-nios2nommu/pio_struct.h
+new file mode 100644
+index 0000000..8ce5176
+--- /dev/null
++++ b/include/asm-nios2nommu/pio_struct.h
+@@ -0,0 +1,14 @@
++// PIO Peripheral
++
++// PIO Registers
++typedef volatile struct
++ {
++ int np_piodata; // read/write, up to 32 bits
++ int np_piodirection; // write/readable, up to 32 bits, 1->output bit
++ int np_piointerruptmask; // write/readable, up to 32 bits, 1->enable interrupt
++ int np_pioedgecapture; // read, up to 32 bits, cleared by any write
++ } np_pio;
++
++// PIO Routines
++void nr_pio_showhex(int value); // shows low byte on pio named na_seven_seg_pio
++
+diff --git a/include/asm-nios2nommu/poll.h b/include/asm-nios2nommu/poll.h
+new file mode 100644
+index 0000000..f6b9ab8
+--- /dev/null
++++ b/include/asm-nios2nommu/poll.h
+@@ -0,0 +1,48 @@
++#ifndef __NIOS2_POLL_H
++#define __NIOS2_POLL_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/poll.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define POLLIN 1
++#define POLLPRI 2
++#define POLLOUT 4
++#define POLLERR 8
++#define POLLHUP 16
++#define POLLNVAL 32
++#define POLLRDNORM 64
++#define POLLWRNORM POLLOUT
++#define POLLRDBAND 128
++#define POLLWRBAND 256
++#define POLLMSG 0x0400
++#define POLLREMOVE 0x1000
++#define POLLRDHUP 0x2000
++
++struct pollfd {
++ int fd;
++ short events;
++ short revents;
++};
++
++#endif
+diff --git a/include/asm-nios2nommu/posix_types.h b/include/asm-nios2nommu/posix_types.h
+new file mode 100644
+index 0000000..0b019b5
+--- /dev/null
++++ b/include/asm-nios2nommu/posix_types.h
+@@ -0,0 +1,89 @@
++#ifndef __ARCH_NIOS2_POSIX_TYPES_H
++#define __ARCH_NIOS2_POSIX_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/posix_types.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned short __kernel_uid_t;
++typedef unsigned short __kernel_gid_t;
++typedef unsigned int __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__KERNEL__) || defined(__USE_ALL)
++ int val[2];
++#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++ int __val[2];
++#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++} __kernel_fsid_t;
++
++#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
++
++#undef __FD_SET
++#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
++
++#undef __FD_CLR
++#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
++
++#undef __FD_ISSET
++#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
++
++#undef __FD_ZERO
++#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
++
++#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
++
++#endif
+diff --git a/include/asm-nios2nommu/preem_latency.h b/include/asm-nios2nommu/preem_latency.h
+new file mode 100644
+index 0000000..6defb5c
+--- /dev/null
++++ b/include/asm-nios2nommu/preem_latency.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_PREEM_LATENCY_H
++#define _ASM_PREEM_LATENCY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/preem_latency.h
++ *
++ * timing support for preempt-stats patch
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++#define readclock(low) \
++do {\
++ *(volatile unsigned long *)na_Counter_64_bit=1; \
++ low=*(volatile unsigned long *)na_Counter_64_bit; \
++} while (0)
++#define readclock_init()
++
++#endif /* _ASM_PREEM_LATENCY_H */
+diff --git a/include/asm-nios2nommu/processor.h b/include/asm-nios2nommu/processor.h
+new file mode 100644
+index 0000000..5332f94
+--- /dev/null
++++ b/include/asm-nios2nommu/processor.h
+@@ -0,0 +1,148 @@
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/processor.h
++ *
++ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2001 Ken Hill (khill@microtronix.com)
++ * Vic Phillips (vic@microtronix.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * hacked from:
++ * include/asm-sparc/processor.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ * Nov/02/2003 dgt Fix task_size
++ *
++ ---------------------------------------------------------------------*/
++
++#ifndef __ASM_NIOS_PROCESSOR_H
++#define __ASM_NIOS_PROCESSOR_H
++
++#define NIOS2_FLAG_KTHREAD 0x00000001 /* task is a kernel thread */
++#define NIOS2_FLAG_COPROC 0x00000002 /* Thread used coprocess */
++#define NIOS2_FLAG_DEBUG 0x00000004 /* task is being debugged */
++
++#define NIOS2_OP_NOP 0x1883a
++#define NIOS2_OP_BREAK 0x3da03a
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l;})
++
++#include <linux/a.out.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/signal.h>
++#include <asm/segment.h>
++#include <asm/current.h>
++#include <asm/system.h> /* for get_hi_limit */
++
++/*
++ * Bus types
++ */
++#define EISA_bus 0
++#define EISA_bus__is_a_macro /* for versions in ksyms.c */
++#define MCA_bus 0
++#define MCA_bus__is_a_macro /* for versions in ksyms.c */
++
++/*
++ * The nios has no problems with write protection
++ */
++#define wp_works_ok 1
++#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
++
++/* Whee, this is STACK_TOP and the lowest kernel address too... */
++#if 0
++#define KERNBASE 0x00000000 /* First address the kernel will eventually be */
++#define TASK_SIZE (KERNBASE)
++#define MAX_USER_ADDR TASK_SIZE
++#define MMAP_SEARCH_START (TASK_SIZE/3)
++#endif
++
++#define TASK_SIZE ((unsigned int) nasys_program_mem_end) //...this is better...
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
++ * space during mmap's. We won't be using it
++ */
++#define TASK_UNMAPPED_BASE 0
++
++/* The Nios processor specific thread struct. */
++struct thread_struct {
++ struct pt_regs *kregs;
++
++ /* For signal handling */
++ unsigned long sig_address;
++ unsigned long sig_desc;
++
++ /* Context switch saved kernel state. */
++ unsigned long ksp;
++ unsigned long kpsr;
++ unsigned long kesr;
++
++ /* Flags are defined below */
++
++ unsigned long flags;
++ int current_ds;
++ struct exec core_exec; /* just what it says. */
++};
++
++#define INIT_MMAP { &init_mm, (0), (0), \
++ __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC }
++
++#define INIT_THREAD { \
++ .kregs = 0, \
++ .sig_address = 0, \
++ .sig_desc = 0, \
++ .ksp = 0, \
++ .kpsr = 0, \
++ .kesr = PS_S, \
++ .flags = NIOS2_FLAG_KTHREAD, \
++ .current_ds = __KERNEL_DS, \
++ .core_exec = INIT_EXEC \
++}
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++extern unsigned long thread_saved_pc(struct task_struct *t);
++
++extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++#define prepare_to_copy(tsk) do { } while (0)
++
++extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define KSTK_EIP(tsk) ((tsk)->thread.kregs->ea)
++#define KSTK_ESP(tsk) ((tsk)->thread.kregs->sp)
++
++#ifdef __KERNEL__
++/* Allocation and freeing of basic task resources. */
++
++//;dgt2;#define alloc_task_struct() ((struct task_struct *) xx..see..linux..fork..xx __get_free_pages(GFP_KERNEL,1))
++//;dgt2;#define get_task_struct(tsk) xx..see..linux..sched.h...atomic_inc(&mem_map[MAP_NR(tsk)].count)
++
++#endif
++
++#define cpu_relax() do { } while (0)
++#endif /* __ASSEMBLY__ */
++#endif /* __ASM_NIOS_PROCESSOR_H */
+diff --git a/include/asm-nios2nommu/ptrace.h b/include/asm-nios2nommu/ptrace.h
+new file mode 100644
+index 0000000..d669e08
+--- /dev/null
++++ b/include/asm-nios2nommu/ptrace.h
+@@ -0,0 +1,140 @@
++/*
++ * Taken from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_PTRACE_H
++#define _NIOS2NOMMU_PTRACE_H
++
++#ifndef __ASSEMBLY__
++
++#define PTR_R0 0
++#define PTR_R1 1
++#define PTR_R2 2
++#define PTR_R3 3
++#define PTR_R4 4
++#define PTR_R5 5
++#define PTR_R6 6
++#define PTR_R7 7
++#define PTR_R8 8
++#define PTR_R9 9
++#define PTR_R10 10
++#define PTR_R11 11
++#define PTR_R12 12
++#define PTR_R13 13
++#define PTR_R14 14
++#define PTR_R15 15
++#define PTR_R16 16
++#define PTR_R17 17
++#define PTR_R18 18
++#define PTR_R19 19
++#define PTR_R20 20
++#define PTR_R21 21
++#define PTR_R22 22
++#define PTR_R23 23
++#define PTR_R24 24
++#define PTR_R25 25
++#define PTR_GP 26
++#define PTR_SP 27
++#define PTR_FP 28
++#define PTR_EA 29
++#define PTR_BA 30
++#define PTR_RA 31
++#define PTR_STATUS 32
++#define PTR_ESTATUS 33
++#define PTR_BSTATUS 34
++#define PTR_IENABLE 35
++#define PTR_IPENDING 36
++
++/* this struct defines the way the registers are stored on the
++ stack during a system call.
++
++ There is a fake_regs in setup.c that has to match pt_regs.*/
++
++struct pt_regs {
++ unsigned long r8;
++ unsigned long r9;
++ unsigned long r10;
++ unsigned long r11;
++ unsigned long r12;
++ unsigned long r13;
++ unsigned long r14;
++ unsigned long r15;
++ unsigned long r1;
++ unsigned long r2;
++ unsigned long r3;
++ unsigned long r4;
++ unsigned long r5;
++ unsigned long r6;
++ unsigned long r7;
++ unsigned long orig_r2;
++ unsigned long ra;
++ unsigned long fp;
++ unsigned long sp;
++ unsigned long gp;
++ unsigned long estatus;
++ unsigned long status_extension;
++ unsigned long ea;
++};
++
++
++/*
++ * This is the extended stack used by signal handlers and the context
++ * switcher: it's pushed after the normal "struct pt_regs".
++ */
++struct switch_stack {
++ unsigned long r16;
++ unsigned long r17;
++ unsigned long r18;
++ unsigned long r19;
++ unsigned long r20;
++ unsigned long r21;
++ unsigned long r22;
++ unsigned long r23;
++ unsigned long fp;
++ unsigned long gp;
++ unsigned long ra;
++};
++
++#ifdef __KERNEL__
++/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
++#define PTRACE_GETREGS 12
++#define PTRACE_SETREGS 13
++#ifdef CONFIG_FPU
++#define PTRACE_GETFPREGS 14
++#define PTRACE_SETFPREGS 15
++#endif
++
++#ifndef PS_S
++#define PS_S (0x00000001)
++#endif
++#ifndef PS_T
++#define PS_T (0x00000002)
++#endif
++
++#define user_mode(regs) (!((regs)->status_extension & PS_S))
++#define instruction_pointer(regs) ((regs)->ra)
++#define profile_pc(regs) instruction_pointer(regs)
++extern void show_regs(struct pt_regs *);
++
++#endif /* __KERNEL__ */
++#endif /* __ASSEMBLY__ */
++#endif /* _NIOS2NOMMU_PTRACE_H */
+diff --git a/include/asm-nios2nommu/resource.h b/include/asm-nios2nommu/resource.h
+new file mode 100644
+index 0000000..9c2499a
+--- /dev/null
++++ b/include/asm-nios2nommu/resource.h
+@@ -0,0 +1,6 @@
++#ifndef __ASM_SH_RESOURCE_H
++#define __ASM_SH_RESOURCE_H
++
++#include <asm-generic/resource.h>
++
++#endif /* __ASM_SH_RESOURCE_H */
+diff --git a/include/asm-nios2nommu/rmap.h b/include/asm-nios2nommu/rmap.h
+new file mode 100644
+index 0000000..b3664cc
+--- /dev/null
++++ b/include/asm-nios2nommu/rmap.h
+@@ -0,0 +1,2 @@
++/* Do not need anything here */
++
+diff --git a/include/asm-nios2nommu/scatterlist.h b/include/asm-nios2nommu/scatterlist.h
+new file mode 100644
+index 0000000..20898e2
+--- /dev/null
++++ b/include/asm-nios2nommu/scatterlist.h
+@@ -0,0 +1,13 @@
++#ifndef __ASM_SH_SCATTERLIST_H
++#define __ASM_SH_SCATTERLIST_H
++
++struct scatterlist {
++ struct page * page; /* Location for highmem page, if any */
++ unsigned int offset;/* for highmem, page offset */
++ dma_addr_t dma_address;
++ unsigned int length;
++};
++
++#define ISA_DMA_THRESHOLD (0xffffffff)
++
++#endif /* !(__ASM_SH_SCATTERLIST_H) */
+diff --git a/include/asm-nios2nommu/sections.h b/include/asm-nios2nommu/sections.h
+new file mode 100644
+index 0000000..61b3f71
+--- /dev/null
++++ b/include/asm-nios2nommu/sections.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_SECTIONS_H
++#define _NIOS2NOMMU_SECTIONS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sections.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/sections.h>
++
++#endif /* _NIOS2NOMMU_SECTIONS_H */
+diff --git a/include/asm-nios2nommu/segment.h b/include/asm-nios2nommu/segment.h
+new file mode 100644
+index 0000000..25871b3
+--- /dev/null
++++ b/include/asm-nios2nommu/segment.h
+@@ -0,0 +1,75 @@
++#ifndef _NIOS2NOMMU_SEGMENT_H
++#define _NIOS2NOMMU_SEGMENT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/segment.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* define constants */
++/* Address spaces (FC0-FC2) */
++#define USER_DATA (1)
++#ifndef __USER_DS
++#define __USER_DS (USER_DATA)
++#endif
++#define USER_PROGRAM (2)
++#define SUPER_DATA (5)
++#ifndef __KERNEL_DS
++#define __KERNEL_DS (SUPER_DATA)
++#endif
++#define SUPER_PROGRAM (6)
++#define CPU_SPACE (7)
++
++#ifndef __ASSEMBLY__
++
++typedef struct {
++ unsigned long seg;
++} mm_segment_t;
++
++#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
++#define USER_DS MAKE_MM_SEG(__USER_DS)
++#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
++
++/*
++ * Get/set the SFC/DFC registers for MOVES instructions
++ */
++
++static inline mm_segment_t get_fs(void)
++{
++ return USER_DS;
++}
++
++static inline mm_segment_t get_ds(void)
++{
++ /* return the supervisor data space code */
++ return KERNEL_DS;
++}
++
++static inline void set_fs(mm_segment_t val)
++{
++}
++
++#define segment_eq(a,b) ((a).seg == (b).seg)
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _NIOS2NOMMU_SEGMENT_H */
+diff --git a/include/asm-nios2nommu/semaphore-helper.h b/include/asm-nios2nommu/semaphore-helper.h
+new file mode 100644
+index 0000000..a8905d1
+--- /dev/null
++++ b/include/asm-nios2nommu/semaphore-helper.h
+@@ -0,0 +1,99 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_HELPER_H
++#define _NIOS2NOMMU_SEMAPHORE_HELPER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * SMP- and interrupt-safe semaphores helper functions.
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++/*
++ * These two _must_ execute atomically wrt each other.
++ */
++static inline void wake_one_more(struct semaphore * sem)
++{
++ atomic_inc(&sem->waking);
++}
++
++static inline int waking_non_zero(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_interruptible:
++ * 1 got the lock
++ * 0 go to sleep
++ * -EINTR interrupted
++ */
++static inline int waking_non_zero_interruptible(struct semaphore *sem,
++ struct task_struct *tsk)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ } else if (signal_pending(tsk)) {
++ atomic_inc(&sem->count);
++ ret = -EINTR;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_trylock:
++ * 1 failed to lock
++ * 0 got the lock
++ */
++static inline int waking_non_zero_trylock(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 1;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 0;
++ } else
++ atomic_inc(&sem->count);
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++#endif
+diff --git a/include/asm-nios2nommu/semaphore.h b/include/asm-nios2nommu/semaphore.h
+new file mode 100644
+index 0000000..8d66c77
+--- /dev/null
++++ b/include/asm-nios2nommu/semaphore.h
+@@ -0,0 +1,152 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_H
++#define _NIOS2NOMMU_SEMAPHORE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * Interrupt-safe semaphores..
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define RW_LOCK_BIAS 0x01000000
++
++#ifndef __ASSEMBLY__
++
++#include <linux/linkage.h>
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++
++#include <asm/system.h>
++#include <asm/atomic.h>
++
++struct semaphore {
++ atomic_t count;
++ atomic_t waking;
++ wait_queue_head_t wait;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n) \
++{ \
++ .count = ATOMIC_INIT(n), \
++ .waking = ATOMIC_INIT(0), \
++ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
++}
++
++#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
++ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
++
++#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
++#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
++
++static inline void sema_init (struct semaphore *sem, int val)
++{
++ *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
++}
++
++static inline void init_MUTEX (struct semaphore *sem)
++{
++ sema_init(sem, 1);
++}
++
++static inline void init_MUTEX_LOCKED (struct semaphore *sem)
++{
++ sema_init(sem, 0);
++}
++
++asmlinkage void __down_failed(void /* special register calling convention */);
++asmlinkage int __down_failed_interruptible(void /* params in registers */);
++asmlinkage int __down_failed_trylock(void /* params in registers */);
++asmlinkage void __up_wakeup(void /* special register calling convention */);
++
++asmlinkage void __down(struct semaphore * sem);
++asmlinkage int __down_interruptible(struct semaphore * sem);
++asmlinkage int __down_trylock(struct semaphore * sem);
++asmlinkage void __up(struct semaphore * sem);
++
++extern spinlock_t semaphore_wake_lock;
++
++/*
++ * This is ugly, but we want the default case to fall through.
++ * "down_failed" is a special asm handler that calls the C
++ * routine that actually waits.
++ */
++static inline void down(struct semaphore * sem)
++{
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if (atomic_dec_return(&sem->count) < 0)
++ __down(sem);
++ #endif
++}
++
++static inline int down_interruptible(struct semaphore * sem)
++{
++ int ret = 0;
++
++
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if(atomic_dec_return(&sem->count) < 0)
++ ret = __down_interruptible(sem);
++ return ret;
++ #endif
++}
++
++static inline int down_trylock(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ int ret = 0;
++
++ if (atomic_dec_return (&sem->count) < 0)
++ ret = __down_trylock(sem);
++ return ret;
++ #endif
++}
++
++/*
++ * Note! This is subtle. We jump to wake people up only if
++ * the semaphore was negative (== somebody was waiting on it).
++ * The default case (no contention) will result in NO
++ * jumps for both down() and up().
++ */
++static inline void up(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "increment memory"....
++ #else
++ if (atomic_inc_return(&sem->count) <= 0)
++ __up(sem);
++ #endif
++}
++
++#endif /* __ASSEMBLY__ */
++
++#endif
+diff --git a/include/asm-nios2nommu/sembuf.h b/include/asm-nios2nommu/sembuf.h
+new file mode 100644
+index 0000000..e530cab
+--- /dev/null
++++ b/include/asm-nios2nommu/sembuf.h
+@@ -0,0 +1,48 @@
++#ifndef _NIOS_SEMBUF_H
++#define _NIOS_SEMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sembuf.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct semid64_ds {
++ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
++ __kernel_time_t sem_otime; /* last semop time */
++ unsigned long __unused1;
++ __kernel_time_t sem_ctime; /* last change time */
++ unsigned long __unused2;
++ unsigned long sem_nsems; /* no. of semaphores in array */
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SEMBUF_H */
+diff --git a/include/asm-nios2nommu/setup.h b/include/asm-nios2nommu/setup.h
+new file mode 100644
+index 0000000..c5a655a
+--- /dev/null
++++ b/include/asm-nios2nommu/setup.h
+@@ -0,0 +1,31 @@
++/* Copied from i386 port.
++ * Just a place holder. We don't want to have to test x86 before
++ * we include stuff
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SETUP_H
++#define _NIOS2_SETUP_H
++
++#define COMMAND_LINE_SIZE 512
++
++#endif /* _NIOS2_SETUP_H */
+diff --git a/include/asm-nios2nommu/shmbuf.h b/include/asm-nios2nommu/shmbuf.h
+new file mode 100644
+index 0000000..f6e6e7d
+--- /dev/null
++++ b/include/asm-nios2nommu/shmbuf.h
+@@ -0,0 +1,64 @@
++#ifndef _NIOS_SHMBUF_H
++#define _NIOS_SHMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmbuf.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct shmid64_ds {
++ struct ipc64_perm shm_perm; /* operation perms */
++ size_t shm_segsz; /* size of segment (bytes) */
++ __kernel_time_t shm_atime; /* last attach time */
++ unsigned long __unused1;
++ __kernel_time_t shm_dtime; /* last detach time */
++ unsigned long __unused2;
++ __kernel_time_t shm_ctime; /* last change time */
++ unsigned long __unused3;
++ __kernel_pid_t shm_cpid; /* pid of creator */
++ __kernel_pid_t shm_lpid; /* pid of last operator */
++ unsigned long shm_nattch; /* no. of current attaches */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++struct shminfo64 {
++ unsigned long shmmax;
++ unsigned long shmmin;
++ unsigned long shmmni;
++ unsigned long shmseg;
++ unsigned long shmall;
++ unsigned long __unused1;
++ unsigned long __unused2;
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SHMBUF_H */
+diff --git a/include/asm-nios2nommu/shmparam.h b/include/asm-nios2nommu/shmparam.h
+new file mode 100644
+index 0000000..94efe2d
+--- /dev/null
++++ b/include/asm-nios2nommu/shmparam.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS2NOMMU_SHMPARAM_H__
++#define __NIOS2NOMMU_SHMPARAM_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmparam.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
++
++#endif /* __NIOS2NOMMU_SHMPARAM_H__ */
+diff --git a/include/asm-nios2nommu/sigcontext.h b/include/asm-nios2nommu/sigcontext.h
+new file mode 100644
+index 0000000..7321e7d
+--- /dev/null
++++ b/include/asm-nios2nommu/sigcontext.h
+@@ -0,0 +1,35 @@
++/*
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_SIGCONTEXT_H
++#define _ASM_NIOS2NOMMU_SIGCONTEXT_H
++
++#include <asm/ptrace.h>
++
++struct sigcontext {
++ struct pt_regs regs;
++ unsigned long sc_mask; /* old sigmask */
++};
++
++#endif
+diff --git a/include/asm-nios2nommu/siginfo.h b/include/asm-nios2nommu/siginfo.h
+new file mode 100644
+index 0000000..c047c0b
+--- /dev/null
++++ b/include/asm-nios2nommu/siginfo.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SIGINFO_H
++#define _NIOS2NOMMU_SIGINFO_H
++
++#include <asm-generic/siginfo.h>
++
++#endif
+diff --git a/include/asm-nios2nommu/signal.h b/include/asm-nios2nommu/signal.h
+new file mode 100644
+index 0000000..c86a20c
+--- /dev/null
++++ b/include/asm-nios2nommu/signal.h
+@@ -0,0 +1,181 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SIGNAL_H
++#define _NIOS2_SIGNAL_H
++
++#include <linux/types.h>
++
++/* Avoid too many header ordering problems. */
++struct siginfo;
++
++#ifdef __KERNEL__
++/* Most things should be clean enough to redefine this at will, if care
++ is taken to make libc match. */
++
++#define _NSIG 64
++#define _NSIG_BPW 32
++#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
++
++typedef unsigned long old_sigset_t; /* at least 32 bits */
++
++typedef struct {
++ unsigned long sig[_NSIG_WORDS];
++} sigset_t;
++
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++#define NSIG 32
++typedef unsigned long sigset_t;
++
++#endif /* __KERNEL__ */
++
++#define SIGHUP 1
++#define SIGINT 2
++#define SIGQUIT 3
++#define SIGILL 4
++#define SIGTRAP 5
++#define SIGABRT 6
++#define SIGIOT 6
++#define SIGBUS 7
++#define SIGFPE 8
++#define SIGKILL 9
++#define SIGUSR1 10
++#define SIGSEGV 11
++#define SIGUSR2 12
++#define SIGPIPE 13
++#define SIGALRM 14
++#define SIGTERM 15
++#define SIGSTKFLT 16
++#define SIGCHLD 17
++#define SIGCONT 18
++#define SIGSTOP 19
++#define SIGTSTP 20
++#define SIGTTIN 21
++#define SIGTTOU 22
++#define SIGURG 23
++#define SIGXCPU 24
++#define SIGXFSZ 25
++#define SIGVTALRM 26
++#define SIGPROF 27
++#define SIGWINCH 28
++#define SIGIO 29
++#define SIGPOLL SIGIO
++/*
++#define SIGLOST 29
++*/
++#define SIGPWR 30
++#define SIGSYS 31
++#define SIGUNUSED 31
++
++/* These should not be considered constants from userland. */
++#define SIGRTMIN 32
++#define SIGRTMAX _NSIG
++
++/*
++ * SA_FLAGS values:
++ *
++ * SA_ONSTACK indicates that a registered stack_t will be used.
++ * SA_RESTART flag to get restarting signals (which were the default long ago)
++ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
++ * SA_RESETHAND clears the handler when the signal is delivered.
++ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
++ * SA_NODEFER prevents the current signal from being masked in the handler.
++ *
++ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
++ * Unix names RESETHAND and NODEFER respectively.
++ */
++#define SA_NOCLDSTOP 0x00000001
++#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
++#define SA_SIGINFO 0x00000004
++#define SA_ONSTACK 0x08000000
++#define SA_RESTART 0x10000000
++#define SA_NODEFER 0x40000000
++#define SA_RESETHAND 0x80000000
++
++#define SA_NOMASK SA_NODEFER
++#define SA_ONESHOT SA_RESETHAND
++
++/*
++ * sigaltstack controls
++ */
++#define SS_ONSTACK 1
++#define SS_DISABLE 2
++
++#define MINSIGSTKSZ 2048
++#define SIGSTKSZ 8192
++
++#include <asm-generic/signal.h>
++
++#ifdef __KERNEL__
++struct old_sigaction {
++ __sighandler_t sa_handler;
++ old_sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++struct sigaction {
++ __sighandler_t sa_handler;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++ sigset_t sa_mask; /* mask last for extensibility */
++};
++
++struct k_sigaction {
++ struct sigaction sa;
++};
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++struct sigaction {
++ union {
++ __sighandler_t _sa_handler;
++ void (*_sa_sigaction)(int, struct siginfo *, void *);
++ } _u;
++ sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++#define sa_handler _u._sa_handler
++#define sa_sigaction _u._sa_sigaction
++
++#endif /* __KERNEL__ */
++
++typedef struct sigaltstack {
++ void *ss_sp;
++ int ss_flags;
++ size_t ss_size;
++} stack_t;
++
++#ifdef __KERNEL__
++
++#include <asm/sigcontext.h>
++#undef __HAVE_ARCH_SIG_BITOPS
++
++#define ptrace_signal_deliver(regs, cookie) do { } while (0)
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_SIGNAL_H */
+diff --git a/include/asm-nios2nommu/smp.h b/include/asm-nios2nommu/smp.h
+new file mode 100644
+index 0000000..fb23307
+--- /dev/null
++++ b/include/asm-nios2nommu/smp.h
+@@ -0,0 +1,32 @@
++#ifndef __ASM_SMP_H
++#define __ASM_SMP_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/smp.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef CONFIG_SMP
++#error SMP not supported
++#endif
++
++#endif
+diff --git a/include/asm-nios2nommu/socket.h b/include/asm-nios2nommu/socket.h
+new file mode 100644
+index 0000000..5452e2b
+--- /dev/null
++++ b/include/asm-nios2nommu/socket.h
+@@ -0,0 +1,79 @@
++#ifndef _ASM_SOCKET_H
++#define _ASM_SOCKET_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/socket.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/sockios.h>
++
++/* For setsockopt(2) */
++#define SOL_SOCKET 1
++
++#define SO_DEBUG 1
++#define SO_REUSEADDR 2
++#define SO_TYPE 3
++#define SO_ERROR 4
++#define SO_DONTROUTE 5
++#define SO_BROADCAST 6
++#define SO_SNDBUF 7
++#define SO_RCVBUF 8
++#define SO_SNDBUFFORCE 32
++#define SO_RCVBUFFORCE 33
++#define SO_KEEPALIVE 9
++#define SO_OOBINLINE 10
++#define SO_NO_CHECK 11
++#define SO_PRIORITY 12
++#define SO_LINGER 13
++#define SO_BSDCOMPAT 14
++/* To add :#define SO_REUSEPORT 15 */
++#define SO_PASSCRED 16
++#define SO_PEERCRED 17
++#define SO_RCVLOWAT 18
++#define SO_SNDLOWAT 19
++#define SO_RCVTIMEO 20
++#define SO_SNDTIMEO 21
++
++/* Security levels - as per NRL IPv6 - don't actually do anything */
++#define SO_SECURITY_AUTHENTICATION 22
++#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
++#define SO_SECURITY_ENCRYPTION_NETWORK 24
++
++#define SO_BINDTODEVICE 25
++
++/* Socket filtering */
++#define SO_ATTACH_FILTER 26
++#define SO_DETACH_FILTER 27
++
++#define SO_PEERNAME 28
++#define SO_TIMESTAMP 29
++#define SCM_TIMESTAMP SO_TIMESTAMP
++
++#define SO_ACCEPTCONN 30
++
++#define SO_PEERSEC 31 /* ;dgt2;tmp; */
++#define SO_PASSSEC 34
++#define SO_TIMESTAMPNS 35
++#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
++
++#endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-nios2nommu/sockios.h b/include/asm-nios2nommu/sockios.h
+new file mode 100644
+index 0000000..c604aa7
+--- /dev/null
++++ b/include/asm-nios2nommu/sockios.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_NIOS_SOCKIOS_H
++#define _ASM_NIOS_SOCKIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sockios.h
++ *
++ * Socket-level I/O control calls.
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define FIOSETOWN 0x8901
++#define SIOCSPGRP 0x8902
++#define FIOGETOWN 0x8903
++#define SIOCGPGRP 0x8904
++#define SIOCATMARK 0x8905
++#define SIOCGSTAMP 0x8906 /* Get stamp */
++#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
++
++#endif /* !(_ASM_NIOS_SOCKIOS_H) */
++
+diff --git a/include/asm-nios2nommu/spi.h b/include/asm-nios2nommu/spi.h
+new file mode 100644
+index 0000000..6efb82c
+--- /dev/null
++++ b/include/asm-nios2nommu/spi.h
+@@ -0,0 +1,92 @@
++#ifndef _ASM_SPI_H_
++#define _ASM_SPI_H_ 1
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spi.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++int register_NIOS_SPI( void );
++void unregister_NIOS_SPI( void );
++
++#if defined(MODULE)
++void cleanup_module( void );
++int init_module( void );
++#endif
++
++#if defined(__KERNEL__)
++int spi_reset ( void );
++#endif
++
++
++#define clockCS 0x01
++#define temperatureCS 0x02
++
++#define clock_read_base 0x00
++#define clock_write_base 0x80
++#define clock_read_control 0x0F
++#define clock_read_trickle 0x11
++
++#define clock_read_sec 0x00
++#define clock_read_min 0x01
++#define clock_read_hour 0x02
++#define clock_read_day 0x03
++#define clock_read_date 0x04
++#define clock_read_month 0x05
++#define clock_read_year 0x06
++
++#define clock_write_control 0x8F
++#define clock_write_trickle 0x91
++#define clock_write_sec 0x80
++#define clock_write_min 0x81
++#define clock_write_hour 0x82
++#define clock_write_day 0x83
++#define clock_write_date 0x84
++#define clock_write_month 0x85
++#define clock_write_year 0x86
++
++#define clock_write_ram_start 0xA0
++#define clock_write_ram_end 0x100
++#define clock_read_ram_start 0x20
++#define clock_read_ram_end 0x80
++
++
++#define clock_sec_def 0x11
++#define clock_min_def 0x59
++#define clock_hour_def 0x71
++#define clock_day_def 0x00
++#define clock_date_def 0x20
++#define clock_month_def 0x12
++#define clock_year_def 0x34
++
++#define temp_read_base 0x00
++#define temp_write_base 0x80
++#define temp_read_control 0x00
++#define temp_write_control 0x80
++#define temp_read_msb 0x02
++#define temp_read_lsb 0x01
++
++#define MAX_TEMP_VAR 10
++
++#endif /*_ASM_SPI_H_*/
+diff --git a/include/asm-nios2nommu/spi_struct.h b/include/asm-nios2nommu/spi_struct.h
+new file mode 100644
+index 0000000..c7b2faf
+--- /dev/null
++++ b/include/asm-nios2nommu/spi_struct.h
+@@ -0,0 +1,57 @@
++// SPI Registers
++typedef volatile struct
++ {
++ int np_spirxdata; // Read-only, 1-16 bit
++ int np_spitxdata; // Write-only, same width as rxdata
++ int np_spistatus; // Read-only, 9-bit
++ int np_spicontrol; // Read/Write, 9-bit
++ int np_spireserved; // reserved
++ int np_spislaveselect; // Read/Write, 1-16 bit, master only
++ int np_spiendofpacket; // Read/write, same width as txdata, rxdata.
++ } np_spi;
++
++// SPI Status Register Bits
++enum
++ {
++ np_spistatus_eop_bit = 9,
++ np_spistatus_e_bit = 8,
++ np_spistatus_rrdy_bit = 7,
++ np_spistatus_trdy_bit = 6,
++ np_spistatus_tmt_bit = 5,
++ np_spistatus_toe_bit = 4,
++ np_spistatus_roe_bit = 3,
++
++ np_spistatus_eop_mask = (1 << 9),
++ np_spistatus_e_mask = (1 << 8),
++ np_spistatus_rrdy_mask = (1 << 7),
++ np_spistatus_trdy_mask = (1 << 6),
++ np_spistatus_tmt_mask = (1 << 5),
++ np_spistatus_toe_mask = (1 << 4),
++ np_spistatus_roe_mask = (1 << 3),
++ };
++
++// SPI Control Register Bits
++enum
++ {
++ np_spicontrol_sso_bit = 10,
++ np_spicontrol_ieop_bit = 9,
++ np_spicontrol_ie_bit = 8,
++ np_spicontrol_irrdy_bit = 7,
++ np_spicontrol_itrdy_bit = 6,
++ np_spicontrol_itoe_bit = 4,
++ np_spicontrol_iroe_bit = 3,
++
++ np_spicontrol_sso_mask = (1 << 10),
++ np_spicontrol_ieop_mask = (1 << 9),
++ np_spicontrol_ie_mask = (1 << 8),
++ np_spicontrol_irrdy_mask = (1 << 7),
++ np_spicontrol_itrdy_mask = (1 << 6),
++ np_spicontrol_itoe_mask = (1 << 4),
++ np_spicontrol_iroe_mask = (1 << 3),
++ };
++
++// SPI Routines.
++int nr_spi_rxchar(np_spi *spiBase);
++int nr_spi_txchar(int i, np_spi *spiBase);
++
++
+diff --git a/include/asm-nios2nommu/spinlock.h b/include/asm-nios2nommu/spinlock.h
+new file mode 100644
+index 0000000..f518755
+--- /dev/null
++++ b/include/asm-nios2nommu/spinlock.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS_SPINLOCK_H
++#define __NIOS_SPINLOCK_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spinlock.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#error "Nios doesn't do SMP yet"
++
++#endif
+diff --git a/include/asm-nios2nommu/stat.h b/include/asm-nios2nommu/stat.h
+new file mode 100644
+index 0000000..bd27a97
+--- /dev/null
++++ b/include/asm-nios2nommu/stat.h
+@@ -0,0 +1,102 @@
++#ifndef _ASMNIOS2NOMMU_STAT_H
++#define _ASMNIOS2NOMMU_STAT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/stat.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct __old_kernel_stat {
++ unsigned short st_dev;
++ unsigned short st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned long st_size;
++ unsigned long st_atime;
++ unsigned long st_mtime;
++ unsigned long st_ctime;
++};
++
++struct stat {
++ unsigned short st_dev;
++ unsigned short __pad1;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned short __pad2;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long __unused1;
++ unsigned long st_mtime;
++ unsigned long __unused2;
++ unsigned long st_ctime;
++ unsigned long __unused3;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++/* This matches struct stat64 in glibc2.1, hence the absolutely
++ * insane amounts of padding around dev_t's.
++ */
++struct stat64 {
++ unsigned long long st_dev;
++ unsigned char __pad1[4];
++
++#define STAT64_HAS_BROKEN_ST_INO 1
++ unsigned long __st_ino;
++
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++ unsigned char __pad3[4];
++
++ long long st_size;
++ unsigned long st_blksize;
++
++ unsigned long __pad4; /* future possible st_blocks high bits */
++ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long long st_ino;
++};
++
++#endif
+diff --git a/include/asm-nios2nommu/statfs.h b/include/asm-nios2nommu/statfs.h
+new file mode 100644
+index 0000000..c4637f6
+--- /dev/null
++++ b/include/asm-nios2nommu/statfs.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_STATFS_H
++#define _NIOS2NOMMU_STATFS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/statfs.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/statfs.h>
++
++#endif /* _NIOS2NOMMU_STATFS_H */
+diff --git a/include/asm-nios2nommu/string.h b/include/asm-nios2nommu/string.h
+new file mode 100644
+index 0000000..7e39479
+--- /dev/null
++++ b/include/asm-nios2nommu/string.h
+@@ -0,0 +1,45 @@
++#ifndef __NIOS_STRING_H__
++#define __NIOS_STRING_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/string.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef __KERNEL__ /* only set these up for kernel code */
++
++#define __HAVE_ARCH_MEMMOVE
++void * memmove(void * d, const void * s, size_t count);
++#define __HAVE_ARCH_MEMCPY
++extern void * memcpy(void *d, const void *s, size_t count);
++#define __HAVE_ARCH_MEMSET
++extern void * memset(void * s,int c,size_t count);
++
++#if 0
++#define __HAVE_ARCH_BCOPY
++#define __HAVE_ARCH_STRLEN
++#endif
++
++#endif /* KERNEL */
++
++#endif /* !(__NIOS_STRING_H__) */
+diff --git a/include/asm-nios2nommu/system.h b/include/asm-nios2nommu/system.h
+new file mode 100644
+index 0000000..7c35af0
+--- /dev/null
++++ b/include/asm-nios2nommu/system.h
+@@ -0,0 +1,172 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SYSTEM_H
++#define _NIOS2NOMMU_SYSTEM_H
++
++#include <linux/linkage.h>
++#include <linux/compiler.h>
++#include <asm/segment.h>
++#include <asm/entry.h>
++#include <asm/nios.h>
++
++/*
++ * switch_to(n) should switch tasks to task ptr, first checking that
++ * ptr isn't the current task, in which case it does nothing. This
++ * also clears the TS-flag if the task we switched to has used the
++ * math co-processor latest.
++ */
++
++/*
++ */
++asmlinkage void resume(void);
++#define switch_to(prev,next,last) \
++{ \
++ void *_last; \
++ __asm__ __volatile__( \
++ "mov r4, %1\n" \
++ "mov r5, %2\n" \
++ "call resume\n" \
++ "mov %0,r4\n" \
++ : "=r" (_last) \
++ : "r" (prev), "r" (next) \
++ : "r4","r5","r7","r8","ra"); \
++ (last) = _last; \
++}
++
++#define local_irq_enable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "ori r8, r8, 1\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_irq_disable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "andi r8, r8, 0xfffe\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_save_flags(x) __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "mov %0, r8\n" \
++ :"=r" (x) : : "r8", "memory")
++
++#define local_irq_restore(x) __asm__ __volatile__ ( \
++ "mov r8, %0\n" \
++ "wrctl status, r8\n" \
++ : :"r" (x) : "memory")
++
++/* For spinlocks etc */
++#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
++
++#define irqs_disabled() \
++({ \
++ unsigned long flags; \
++ local_save_flags(flags); \
++ ((flags & NIOS2_STATUS_PIE_MSK) == 0x0); \
++})
++
++#define iret() __asm__ __volatile__ ("eret": : :"memory", "ea")
++
++/*
++ * Force strict CPU ordering.
++ * Not really required on m68k...
++ */
++#define nop() asm volatile ("nop"::)
++#define mb() asm volatile ("" : : :"memory")
++#define rmb() asm volatile ("" : : :"memory")
++#define wmb() asm volatile ("" : : :"memory")
++#define set_rmb(var, value) do { xchg(&var, value); } while (0)
++#define set_mb(var, value) set_rmb(var, value)
++#define set_wmb(var, value) do { var = value; wmb(); } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb() mb()
++#define smp_rmb() rmb()
++#define smp_wmb() wmb()
++#define smp_read_barrier_depends() read_barrier_depends()
++#else
++#define smp_mb() barrier()
++#define smp_rmb() barrier()
++#define smp_wmb() barrier()
++#define smp_read_barrier_depends() do { } while(0)
++#endif
++
++#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
++#define tas(ptr) (xchg((ptr),1))
++
++struct __xchg_dummy { unsigned long a[100]; };
++#define __xg(x) ((volatile struct __xchg_dummy *)(x))
++
++static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++{
++ unsigned long tmp, flags;
++
++ local_irq_save(flags);
++
++ switch (size) {
++ case 1:
++ __asm__ __volatile__( \
++ "ldb %0, %2\n" \
++ "stb %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 2:
++ __asm__ __volatile__( \
++ "ldh %0, %2\n" \
++ "sth %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 4:
++ __asm__ __volatile__( \
++ "ldw %0, %2\n" \
++ "stw %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ }
++ local_irq_restore(flags);
++ return tmp;
++}
++
++/*
++ * Atomic compare and exchange. Compare OLD with MEM, if identical,
++ * store NEW in MEM. Return the initial value in MEM. Success is
++ * indicated by comparing RETURN with OLD.
++ */
++#define __HAVE_ARCH_CMPXCHG 1
++
++static __inline__ unsigned long
++cmpxchg(volatile int *p, int old, int new)
++{
++ unsigned long flags;
++ int prev;
++
++ local_irq_save(flags);
++ if ((prev = *p) == old)
++ *p = new;
++ local_irq_restore(flags);
++ return(prev);
++}
++
++#endif /* _NIOS2NOMMU_SYSTEM_H */
+diff --git a/include/asm-nios2nommu/termbits.h b/include/asm-nios2nommu/termbits.h
+new file mode 100644
+index 0000000..74ef61d
+--- /dev/null
++++ b/include/asm-nios2nommu/termbits.h
+@@ -0,0 +1,210 @@
++#ifndef __ARCH_NIOS_TERMBITS_H__
++#define __ARCH_NIOS_TERMBITS_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termbits.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/posix_types.h>
++
++typedef unsigned char cc_t;
++typedef unsigned int speed_t;
++typedef unsigned int tcflag_t;
++
++#define NCCS 19
++struct termios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++};
++
++struct ktermios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++ speed_t c_ispeed; /* input speed */
++ speed_t c_ospeed; /* output speed */
++};
++
++/* c_cc characters */
++#define VINTR 0
++#define VQUIT 1
++#define VERASE 2
++#define VKILL 3
++#define VEOF 4
++#define VTIME 5
++#define VMIN 6
++#define VSWTC 7
++#define VSTART 8
++#define VSTOP 9
++#define VSUSP 10
++#define VEOL 11
++#define VREPRINT 12
++#define VDISCARD 13
++#define VWERASE 14
++#define VLNEXT 15
++#define VEOL2 16
++
++
++/* c_iflag bits */
++#define IGNBRK 0000001
++#define BRKINT 0000002
++#define IGNPAR 0000004
++#define PARMRK 0000010
++#define INPCK 0000020
++#define ISTRIP 0000040
++#define INLCR 0000100
++#define IGNCR 0000200
++#define ICRNL 0000400
++#define IUCLC 0001000
++#define IXON 0002000
++#define IXANY 0004000
++#define IXOFF 0010000
++#define IMAXBEL 0020000
++#define IUTF8 0040000
++
++/* c_oflag bits */
++#define OPOST 0000001
++#define OLCUC 0000002
++#define ONLCR 0000004
++#define OCRNL 0000010
++#define ONOCR 0000020
++#define ONLRET 0000040
++#define OFILL 0000100
++#define OFDEL 0000200
++#define NLDLY 0000400
++#define NL0 0000000
++#define NL1 0000400
++#define CRDLY 0003000
++#define CR0 0000000
++#define CR1 0001000
++#define CR2 0002000
++#define CR3 0003000
++#define TABDLY 0014000
++#define TAB0 0000000
++#define TAB1 0004000
++#define TAB2 0010000
++#define TAB3 0014000
++#define XTABS 0014000
++#define BSDLY 0020000
++#define BS0 0000000
++#define BS1 0020000
++#define VTDLY 0040000
++#define VT0 0000000
++#define VT1 0040000
++#define FFDLY 0100000
++#define FF0 0000000
++#define FF1 0100000
++
++/* c_cflag bit meaning */
++#define CBAUD 0010017
++#define B0 0000000 /* hang up */
++#define B50 0000001
++#define B75 0000002
++#define B110 0000003
++#define B134 0000004
++#define B150 0000005
++#define B200 0000006
++#define B300 0000007
++#define B600 0000010
++#define B1200 0000011
++#define B1800 0000012
++#define B2400 0000013
++#define B4800 0000014
++#define B9600 0000015
++#define B19200 0000016
++#define B38400 0000017
++#define EXTA B19200
++#define EXTB B38400
++#define CSIZE 0000060
++#define CS5 0000000
++#define CS6 0000020
++#define CS7 0000040
++#define CS8 0000060
++#define CSTOPB 0000100
++#define CREAD 0000200
++#define PARENB 0000400
++#define PARODD 0001000
++#define HUPCL 0002000
++#define CLOCAL 0004000
++#define CBAUDEX 0010000
++#define B57600 0010001
++#define B115200 0010002
++#define B230400 0010003
++#define B460800 0010004
++#define B500000 0010005
++#define B576000 0010006
++#define B921600 0010007
++#define B1000000 0010010
++#define B1152000 0010011
++#define B1500000 0010012
++#define B2000000 0010013
++#define B2500000 0010014
++#define B3000000 0010015
++#define B3500000 0010016
++#define B4000000 0010017
++#define CIBAUD 002003600000 /* input baud rate (not used) */
++#define CMSPAR 010000000000 /* mark or space (stick) parity */
++#define CRTSCTS 020000000000 /* flow control */
++
++/* c_lflag bits */
++#define ISIG 0000001
++#define ICANON 0000002
++#define XCASE 0000004
++#define ECHO 0000010
++#define ECHOE 0000020
++#define ECHOK 0000040
++#define ECHONL 0000100
++#define NOFLSH 0000200
++#define TOSTOP 0000400
++#define ECHOCTL 0001000
++#define ECHOPRT 0002000
++#define ECHOKE 0004000
++#define FLUSHO 0010000
++#define PENDIN 0040000
++#define IEXTEN 0100000
++
++
++/* tcflow() and TCXONC use these */
++#define TCOOFF 0
++#define TCOON 1
++#define TCIOFF 2
++#define TCION 3
++
++/* tcflush() and TCFLSH use these */
++#define TCIFLUSH 0
++#define TCOFLUSH 1
++#define TCIOFLUSH 2
++
++/* tcsetattr uses these */
++#define TCSANOW 0
++#define TCSADRAIN 1
++#define TCSAFLUSH 2
++
++#endif /* __ARCH_NIOS_TERMBITS_H__ */
+diff --git a/include/asm-nios2nommu/termios.h b/include/asm-nios2nommu/termios.h
+new file mode 100644
+index 0000000..db0dddf
+--- /dev/null
++++ b/include/asm-nios2nommu/termios.h
+@@ -0,0 +1,132 @@
++#ifndef _NIOS_TERMIOS_H
++#define _NIOS_TERMIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termios.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/termbits.h>
++#include <asm/ioctls.h>
++
++struct winsize {
++ unsigned short ws_row;
++ unsigned short ws_col;
++ unsigned short ws_xpixel;
++ unsigned short ws_ypixel;
++};
++
++#define NCC 8
++struct termio {
++ unsigned short c_iflag; /* input mode flags */
++ unsigned short c_oflag; /* output mode flags */
++ unsigned short c_cflag; /* control mode flags */
++ unsigned short c_lflag; /* local mode flags */
++ unsigned char c_line; /* line discipline */
++ unsigned char c_cc[NCC]; /* control characters */
++};
++
++#ifdef __KERNEL__
++/* intr=^C quit=^| erase=del kill=^U
++ eof=^D vtime=\0 vmin=\1 sxtc=\0
++ start=^Q stop=^S susp=^Z eol=\0
++ reprint=^R discard=^U werase=^W lnext=^V
++ eol2=\0
++*/
++#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
++#endif
++
++/* modem lines */
++#define TIOCM_LE 0x001
++#define TIOCM_DTR 0x002
++#define TIOCM_RTS 0x004
++#define TIOCM_ST 0x008
++#define TIOCM_SR 0x010
++#define TIOCM_CTS 0x020
++#define TIOCM_CAR 0x040
++#define TIOCM_RNG 0x080
++#define TIOCM_DSR 0x100
++#define TIOCM_CD TIOCM_CAR
++#define TIOCM_RI TIOCM_RNG
++#define TIOCM_OUT1 0x2000
++#define TIOCM_OUT2 0x4000
++#define TIOCM_LOOP 0x8000
++
++/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
++
++/* line disciplines */
++#define N_TTY 0
++#define N_SLIP 1
++#define N_MOUSE 2
++#define N_PPP 3
++#define N_STRIP 4
++#define N_AX25 5
++#define N_X25 6 /* X.25 async */
++#define N_6PACK 7
++#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
++#define N_R3964 9 /* Reserved for Simatic R3964 module */
++#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
++#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
++#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
++#define N_HDLC 13 /* synchronous HDLC */
++#define N_SYNC_PPP 14
++#define N_HCI 15 /* Bluetooth HCI UART */
++
++#ifdef __KERNEL__
++
++/*
++ * Translate a "termio" structure into a "termios". Ugh.
++ */
++#define user_termio_to_kernel_termios(termios, termio) \
++({ \
++ unsigned short tmp; \
++ get_user(tmp, &(termio)->c_iflag); \
++ (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
++ get_user(tmp, &(termio)->c_oflag); \
++ (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
++ get_user(tmp, &(termio)->c_cflag); \
++ (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
++ get_user(tmp, &(termio)->c_lflag); \
++ (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
++ get_user((termios)->c_line, &(termio)->c_line); \
++ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
++})
++
++/*
++ * Translate a "termios" structure into a "termio". Ugh.
++ */
++#define kernel_termios_to_user_termio(termio, termios) \
++({ \
++ put_user((termios)->c_iflag, &(termio)->c_iflag); \
++ put_user((termios)->c_oflag, &(termio)->c_oflag); \
++ put_user((termios)->c_cflag, &(termio)->c_cflag); \
++ put_user((termios)->c_lflag, &(termio)->c_lflag); \
++ put_user((termios)->c_line, &(termio)->c_line); \
++ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
++})
++
++#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TERMIOS_H */
+diff --git a/include/asm-nios2nommu/thread_info.h b/include/asm-nios2nommu/thread_info.h
+new file mode 100644
+index 0000000..6d51e0c
+--- /dev/null
++++ b/include/asm-nios2nommu/thread_info.h
+@@ -0,0 +1,127 @@
++/* thread_info.h: niosnommu low-level thread information
++ * adapted from the m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2002 Microtronix Datacom
++ *
++ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_THREAD_INFO_H
++#define _ASM_THREAD_INFO_H
++
++#include <asm/page.h>
++
++#ifdef __KERNEL__
++
++#ifndef __ASSEMBLY__
++
++/*
++ * low level task data.
++ */
++struct thread_info {
++ struct task_struct *task; /* main task structure */
++ struct exec_domain *exec_domain; /* execution domain */
++ unsigned long flags; /* low level flags */
++ int cpu; /* cpu we're on */
++ int preempt_count; /* 0 => preemptable, <0 => BUG*/
++ struct restart_block restart_block;
++};
++
++/*
++ * macros/functions for gaining access to the thread information structure
++ */
++#define INIT_THREAD_INFO(tsk) \
++{ \
++ .task = &tsk, \
++ .exec_domain = &default_exec_domain, \
++ .flags = 0, \
++ .cpu = 0, \
++ .preempt_count = 1, \
++ .restart_block = { \
++ .fn = do_no_restart_syscall, \
++ }, \
++}
++
++#define init_thread_info (init_thread_union.thread_info)
++#define init_stack (init_thread_union.stack)
++
++
++/* how to get the thread information struct from C
++ usable only in supervisor mode */
++static inline struct thread_info *current_thread_info(void)
++{
++ struct thread_info *ti;
++ __asm__ __volatile__(
++ "mov %0, sp\n"
++ "and %0, %0, %1\n"
++ : "=&r"(ti)
++ : "r" (~(THREAD_SIZE-1))
++ );
++ return ti;
++}
++
++/* thread information allocation */
++#define alloc_thread_info(tsk) ((struct thread_info *) \
++ __get_free_pages(GFP_KERNEL, 1))
++#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
++#define put_thread_info(ti) put_task_struct((ti)->task)
++
++#define PREEMPT_ACTIVE 0x4000000
++
++/*
++ * thread information flag bit numbers
++ */
++#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
++#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
++#define TIF_SIGPENDING 2 /* signal pending */
++#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
++#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
++ TIF_NEED_RESCHED */
++#define TIF_MEMDIE 5
++
++/* as above, but as bit values */
++#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
++#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
++#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
++#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
++
++#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
++
++#else /* __ASSEMBLY__ */
++
++/* how to get the thread information struct from ASM
++ usable only in supervisor mode */
++.macro GET_THREAD_INFO reg
++.if THREAD_SIZE & 0xffff0000
++ andhi \reg, sp, %hi(~(THREAD_SIZE-1))
++.else
++ addi \reg, r0, %lo(~(THREAD_SIZE-1))
++ and \reg, \reg, sp
++.endif
++.endm
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_THREAD_INFO_H */
+diff --git a/include/asm-nios2nommu/timer_struct.h b/include/asm-nios2nommu/timer_struct.h
+new file mode 100644
+index 0000000..d811a37
+--- /dev/null
++++ b/include/asm-nios2nommu/timer_struct.h
+@@ -0,0 +1,38 @@
++
++// ----------------------------------------------
++// Timer Peripheral
++
++// Timer Registers
++typedef volatile struct
++ {
++ int np_timerstatus; // read only, 2 bits (any write to clear TO)
++ int np_timercontrol; // write/readable, 4 bits
++ int np_timerperiodl; // write/readable, 16 bits
++ int np_timerperiodh; // write/readable, 16 bits
++ int np_timersnapl; // read only, 16 bits
++ int np_timersnaph; // read only, 16 bits
++ } np_timer;
++
++// Timer Register Bits
++enum
++ {
++ np_timerstatus_run_bit = 1, // timer is running
++ np_timerstatus_to_bit = 0, // timer has timed out
++
++ np_timercontrol_stop_bit = 3, // stop the timer
++ np_timercontrol_start_bit = 2, // start the timer
++ np_timercontrol_cont_bit = 1, // continous mode
++ np_timercontrol_ito_bit = 0, // enable time out interrupt
++
++ np_timerstatus_run_mask = (1<<1), // timer is running
++ np_timerstatus_to_mask = (1<<0), // timer has timed out
++
++ np_timercontrol_stop_mask = (1<<3), // stop the timer
++ np_timercontrol_start_mask = (1<<2), // start the timer
++ np_timercontrol_cont_mask = (1<<1), // continous mode
++ np_timercontrol_ito_mask = (1<<0) // enable time out interrupt
++ };
++
++// Timer Routines
++int nr_timer_milliseconds(void); // Starts on first call, hogs timer1.
++
+diff --git a/include/asm-nios2nommu/timex.h b/include/asm-nios2nommu/timex.h
+new file mode 100644
+index 0000000..abd48cc
+--- /dev/null
++++ b/include/asm-nios2nommu/timex.h
+@@ -0,0 +1,48 @@
++#ifndef _ASMNIOS2NOMMU_TIMEX_H
++#define _ASMNIOS2NOMMU_TIMEX_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/timex.h
++ *
++ * timex specifications
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++
++#define CLOCK_TICK_RATE nasys_clock_freq /* Underlying HZ */
++
++#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
++
++#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
++ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
++ << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
++
++typedef unsigned long cycles_t;
++
++static inline cycles_t get_cycles(void)
++{
++ return 0;
++}
++
++#endif
+diff --git a/include/asm-nios2nommu/tlb.h b/include/asm-nios2nommu/tlb.h
+new file mode 100644
+index 0000000..c597b25
+--- /dev/null
++++ b/include/asm-nios2nommu/tlb.h
+@@ -0,0 +1,35 @@
++#ifndef __NIOS_TLB_H__
++#define __NIOS_TLB_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlb.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd
++ * Copyright (C) 2002 NEC Corporation
++ * Copyright (C) 2002 Miles Bader <miles@gnu.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Written by Miles Bader <miles@gnu.org>
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define tlb_flush(tlb) ((void)0)
++
++#include <asm-generic/tlb.h>
++
++#endif /* __NIOS_TLB_H__ */
++
+diff --git a/include/asm-nios2nommu/tlbflush.h b/include/asm-nios2nommu/tlbflush.h
+new file mode 100644
+index 0000000..63cbe52
+--- /dev/null
++++ b/include/asm-nios2nommu/tlbflush.h
+@@ -0,0 +1,86 @@
++#ifndef _NIOS2NOMMU_TLBFLUSH_H
++#define _NIOS2NOMMU_TLBFLUSH_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlbflush.h
++ *
++ * Ported from m68knommu.
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm/setup.h>
++
++/*
++ * flush all user-space atc entries.
++ */
++static inline void __flush_tlb(void)
++{
++ BUG();
++}
++
++static inline void __flush_tlb_one(unsigned long addr)
++{
++ BUG();
++}
++
++#define flush_tlb() __flush_tlb()
++
++/*
++ * flush all atc entries (both kernel and user-space entries).
++ */
++static inline void flush_tlb_all(void)
++{
++ BUG();
++}
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++ BUG();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
++{
++ BUG();
++}
++
++static inline void flush_tlb_range(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_kernel_page(unsigned long addr)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_pgtables(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++#endif /* _NIOS2NOMMU_TLBFLUSH_H */
+diff --git a/include/asm-nios2nommu/topology.h b/include/asm-nios2nommu/topology.h
+new file mode 100644
+index 0000000..cfe1054
+--- /dev/null
++++ b/include/asm-nios2nommu/topology.h
+@@ -0,0 +1,30 @@
++#ifndef _ASM_NIOS2NOMMU_TOPOLOGY_H
++#define _ASM_NIOS2NOMMU_TOPOLOGY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/topology.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/topology.h>
++
++#endif /* _ASM_NIOS2NOMMU_TOPOLOGY_H */
+diff --git a/include/asm-nios2nommu/traps.h b/include/asm-nios2nommu/traps.h
+new file mode 100644
+index 0000000..e03ef7f
+--- /dev/null
++++ b/include/asm-nios2nommu/traps.h
+@@ -0,0 +1,27 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_TRAPS_H
++#define _NIOS2_TRAPS_H
++
++#define TRAP_ID_SYSCALL 0
++#define TRAP_ID_APPDEBUG 1
++#endif /* !(_NIOS2_TRAPS_H) */
+diff --git a/include/asm-nios2nommu/types.h b/include/asm-nios2nommu/types.h
+new file mode 100644
+index 0000000..dd7a48e
+--- /dev/null
++++ b/include/asm-nios2nommu/types.h
+@@ -0,0 +1,91 @@
++#ifndef _NIOS_TYPES_H
++#define _NIOS_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/types.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is never included by application software unless
++ * explicitly requested (e.g., via linux/types.h) in which case the
++ * application is Linux specific so (user-) name space pollution is
++ * not a major issue. However, for interoperability, libraries still
++ * need to be careful to avoid a name clashes.
++ */
++
++#ifndef __ASSEMBLY__
++
++typedef unsigned short umode_t;
++
++/*
++ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
++ * header files exported to user space
++ */
++
++typedef __signed__ char __s8;
++typedef unsigned char __u8;
++
++typedef __signed__ short __s16;
++typedef unsigned short __u16;
++
++typedef __signed__ int __s32;
++typedef unsigned int __u32;
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++typedef __signed__ long long __s64;
++typedef unsigned long long __u64;
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * These aren't exported outside the kernel to avoid name space clashes
++ */
++#ifdef __KERNEL__
++
++#define BITS_PER_LONG 32
++
++#ifndef __ASSEMBLY__
++
++typedef signed char s8;
++typedef unsigned char u8;
++
++typedef signed short s16;
++typedef unsigned short u16;
++
++typedef signed int s32;
++typedef unsigned int u32;
++
++typedef signed long long s64;
++typedef unsigned long long u64;
++
++/* DMA addresses are always 32-bits wide */
++
++typedef u32 dma_addr_t;
++typedef u32 dma64_addr_t;
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TYPES_H */
+diff --git a/include/asm-nios2nommu/uaccess.h b/include/asm-nios2nommu/uaccess.h
+new file mode 100644
+index 0000000..e7ea20a
+--- /dev/null
++++ b/include/asm-nios2nommu/uaccess.h
+@@ -0,0 +1,184 @@
++#ifndef __NIOS2NOMMU_UACCESS_H
++#define __NIOS2NOMMU_UACCESS_H
++
++/*--------------------------------------------------------------------
++ *
++ * asm-nios2nommu/uaccess.h
++ *
++ * User space memory access functions
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Ported from asm-m68knommu/uaccess.h --wentao
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <asm/segment.h>
++#include <asm/nios.h>
++
++#define VERIFY_READ 0
++#define VERIFY_WRITE 1
++
++#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
++
++static inline int _access_ok(unsigned long addr, unsigned long size)
++{
++ return (((unsigned long)addr < (unsigned long)nasys_program_mem_end) &&
++ (((unsigned long)addr >= (unsigned long)nasys_program_mem)));
++}
++
++extern inline int verify_area(int type, const void * addr, unsigned long size)
++{
++ return access_ok(type,addr,size)?0:-EFAULT;
++}
++
++/*
++ * The exception table consists of pairs of addresses: the first is the
++ * address of an instruction that is allowed to fault, and the second is
++ * the address at which the program should continue. No registers are
++ * modified, so it is entirely up to the continuation code to figure out
++ * what to do.
++ *
++ * All the routines below use bits of fixup code that are out of line
++ * with the main instruction path. This means when everything is well,
++ * we don't even have to jump over them. Further, they do not intrude
++ * on our cache or tlb entries.
++ */
++
++#define ARCH_HAS_SEARCH_EXTABLE
++//;dgt2;tmp;
++
++struct exception_table_entry
++{
++ unsigned long insn, fixup;
++};
++
++/* Returns 0 if exception not found and fixup otherwise. */
++extern unsigned long search_exception_table(unsigned long);
++
++
++/*
++ * These are the main single-value transfer routines. They automatically
++ * use the right size if we just have the right pointer type.
++ */
++
++#define put_user(x, ptr) \
++({ \
++ int __pu_err = 0; \
++ typeof(*(ptr)) __pu_val = (x); \
++ switch (sizeof (*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(ptr, &__pu_val, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __pu_err = __put_user_bad(); \
++ break; \
++ } \
++ __pu_err; \
++})
++#define __put_user(x, ptr) put_user(x, ptr)
++
++extern int __put_user_bad(void);
++
++/*
++ * Tell gcc we read from memory instead of writing: this is because
++ * we do not write to any memory gcc knows about, so there are no
++ * aliasing issues.
++ */
++
++#define __ptr(x) ((unsigned long *)(x))
++
++#define get_user(x, ptr) \
++({ \
++ int __gu_err = 0; \
++ typeof(*(ptr)) __gu_val = 0; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(&__gu_val, ptr, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __gu_val = 0; \
++ __gu_err = __get_user_bad(); \
++ break; \
++ } \
++ (x) = __gu_val; \
++ __gu_err; \
++})
++#define __get_user(x, ptr) get_user(x, ptr)
++
++extern int __get_user_bad(void);
++
++#define copy_from_user(to, from, n) (memcpy(to, from, n), 0)
++#define copy_to_user(to, from, n) (memcpy(to, from, n), 0)
++
++#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
++#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
++#define __copy_to_user_inatomic __copy_to_user
++#define __copy_from_user_inatomic __copy_from_user
++
++#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
++
++#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
++
++/*
++ * Copy a null terminated string from userspace.
++ */
++
++static inline long
++strncpy_from_user(char *dst, const char *src, long count)
++{
++ char *tmp;
++ strncpy(dst, src, count);
++ for (tmp = dst; *tmp && count > 0; tmp++, count--)
++ ;
++ return(tmp - dst); /* DAVIDM should we count a NUL ? check getname */
++}
++
++/*
++ * Return the size of a string (including the ending 0)
++ *
++ * Return 0 on exception, a value greater than N if too long
++ */
++static inline long strnlen_user(const char *src, long n)
++{
++ return(strlen(src) + 1); /* DAVIDM make safer */
++}
++
++#define strlen_user(str) strnlen_user(str, 32767)
++
++/*
++ * Zero Userspace
++ */
++
++static inline unsigned long __clear_user(void *to, unsigned long n)
++{
++ memset(to, 0, n);
++ return(0);
++}
++
++#define clear_user(to, n) __clear_user(to, n)
++
++#endif /* _NIOS2NOMMU_UACCESS_H */
+diff --git a/include/asm-nios2nommu/uart_struct.h b/include/asm-nios2nommu/uart_struct.h
+new file mode 100644
+index 0000000..d955192
+--- /dev/null
++++ b/include/asm-nios2nommu/uart_struct.h
+@@ -0,0 +1,83 @@
++
++// UART Registers
++typedef volatile struct
++ {
++ int np_uartrxdata; // Read-only, 8-bit
++ int np_uarttxdata; // Write-only, 8-bit
++ int np_uartstatus; // Read-only, 8-bit
++ int np_uartcontrol; // Read/Write, 9-bit
++ int np_uartdivisor; // Read/Write, 16-bit, optional
++ int np_uartendofpacket; // Read/Write, end-of-packet character
++ } np_uart;
++
++// UART Status Register Bits
++enum
++ {
++ np_uartstatus_eop_bit = 12,
++ np_uartstatus_cts_bit = 11,
++ np_uartstatus_dcts_bit = 10,
++ np_uartstatus_e_bit = 8,
++ np_uartstatus_rrdy_bit = 7,
++ np_uartstatus_trdy_bit = 6,
++ np_uartstatus_tmt_bit = 5,
++ np_uartstatus_toe_bit = 4,
++ np_uartstatus_roe_bit = 3,
++ np_uartstatus_brk_bit = 2,
++ np_uartstatus_fe_bit = 1,
++ np_uartstatus_pe_bit = 0,
++
++ np_uartstatus_eop_mask = (1<<12),
++ np_uartstatus_cts_mask = (1<<11),
++ np_uartstatus_dcts_mask = (1<<10),
++ np_uartstatus_e_mask = (1<<8),
++ np_uartstatus_rrdy_mask = (1<<7),
++ np_uartstatus_trdy_mask = (1<<6),
++ np_uartstatus_tmt_mask = (1<<5),
++ np_uartstatus_toe_mask = (1<<4),
++ np_uartstatus_roe_mask = (1<<3),
++ np_uartstatus_brk_mask = (1<<2),
++ np_uartstatus_fe_mask = (1<<1),
++ np_uartstatus_pe_mask = (1<<0)
++ };
++
++// UART Control Register Bits
++enum
++ {
++ np_uartcontrol_ieop_bit = 12,
++ np_uartcontrol_rts_bit = 11,
++ np_uartcontrol_idcts_bit = 10,
++ np_uartcontrol_tbrk_bit = 9,
++ np_uartcontrol_ie_bit = 8,
++ np_uartcontrol_irrdy_bit = 7,
++ np_uartcontrol_itrdy_bit = 6,
++ np_uartcontrol_itmt_bit = 5,
++ np_uartcontrol_itoe_bit = 4,
++ np_uartcontrol_iroe_bit = 3,
++ np_uartcontrol_ibrk_bit = 2,
++ np_uartcontrol_ife_bit = 1,
++ np_uartcontrol_ipe_bit = 0,
++
++ np_uartcontrol_ieop_mask = (1<<12),
++ np_uartcontrol_rts_mask = (1<<11),
++ np_uartcontrol_idcts_mask = (1<<10),
++ np_uartcontrol_tbrk_mask = (1<<9),
++ np_uartcontrol_ie_mask = (1<<8),
++ np_uartcontrol_irrdy_mask = (1<<7),
++ np_uartcontrol_itrdy_mask = (1<<6),
++ np_uartcontrol_itmt_mask = (1<<5),
++ np_uartcontrol_itoe_mask = (1<<4),
++ np_uartcontrol_iroe_mask = (1<<3),
++ np_uartcontrol_ibrk_mask = (1<<2),
++ np_uartcontrol_ife_mask = (1<<1),
++ np_uartcontrol_ipe_mask = (1<<0)
++ };
++
++// UART Routines
++int nr_uart_rxchar(np_uart *uartBase); // 0 for default UART
++void nr_uart_txcr(void);
++void nr_uart_txchar(int c,np_uart *uartBase); // 0 for default UART
++void nr_uart_txhex(int x); // 16 or 32 bits
++void nr_uart_txhex16(short x);
++void nr_uart_txhex32(long x);
++void nr_uart_txstring(char *s);
++
+diff --git a/include/asm-nios2nommu/ucontext.h b/include/asm-nios2nommu/ucontext.h
+new file mode 100644
+index 0000000..f2e7ce2
+--- /dev/null
++++ b/include/asm-nios2nommu/ucontext.h
+@@ -0,0 +1,63 @@
++#ifndef _NIOSKNOMMU_UCONTEXT_H
++#define _NIOSKNOMMU_UCONTEXT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/ucontext.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++typedef int greg_t;
++#define NGREG 32
++typedef greg_t gregset_t[NGREG];
++
++#ifdef CONFIG_FPU
++typedef struct fpregset {
++ int f_pcr;
++ int f_psr;
++ int f_fpiaddr;
++ int f_fpregs[8][3];
++} fpregset_t;
++#endif
++
++struct mcontext {
++ int version;
++ int status_extension;
++ gregset_t gregs;
++#ifdef CONFIG_FPU
++ fpregset_t fpregs;
++#endif
++};
++
++#define MCONTEXT_VERSION 2
++
++struct ucontext {
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct mcontext uc_mcontext;
++#ifdef CONFIG_FPU
++ unsigned long uc_filler[80];
++#endif
++ sigset_t uc_sigmask; /* mask last for extensibility */
++};
++
++#endif
+diff --git a/include/asm-nios2nommu/unaligned.h b/include/asm-nios2nommu/unaligned.h
+new file mode 100644
+index 0000000..4876185
+--- /dev/null
++++ b/include/asm-nios2nommu/unaligned.h
+@@ -0,0 +1,6 @@
++#ifndef __NIOS2_UNALIGNED_H
++#define __NIOS2_UNALIGNED_H
++
++#include <asm-generic/unaligned.h>
++
++#endif /* __NIOS2_UNALIGNED_H */
+diff --git a/include/asm-nios2nommu/unistd.h b/include/asm-nios2nommu/unistd.h
+new file mode 100644
+index 0000000..43cd165
+--- /dev/null
++++ b/include/asm-nios2nommu/unistd.h
+@@ -0,0 +1,395 @@
++#ifndef _ASM_NIOS_UNISTD_H_
++#define _ASM_NIOS_UNISTD_H_
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/unistd.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * //vic - kernel_thread moved to process.c
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/traps.h>
++
++/* TRAP isr expects the trap# (syscall=#TRAP_ID_SYSCALL) in r2,
++ * the syscall # in r3, and arguments in r4, r5, ...
++ * Return argument expected in r2.
++ */
++
++#define __NR_restart_syscall 0
++#define __NR_exit 1
++#define __NR_fork 2
++#define __NR_read 3
++#define __NR_write 4
++#define __NR_open 5
++#define __NR_close 6
++#define __NR_waitpid 7
++#define __NR_creat 8
++#define __NR_link 9
++#define __NR_unlink 10
++#define __NR_execve 11
++#define __NR_chdir 12
++#define __NR_time 13
++#define __NR_mknod 14
++#define __NR_chmod 15
++#define __NR_chown 16
++#define __NR_break 17
++#define __NR_oldstat 18
++#define __NR_lseek 19
++#define __NR_getpid 20
++#define __NR_mount 21
++#define __NR_umount 22
++#define __NR_setuid 23
++#define __NR_getuid 24
++#define __NR_stime 25
++#define __NR_ptrace 26
++#define __NR_alarm 27
++#define __NR_oldfstat 28
++#define __NR_pause 29
++#define __NR_utime 30
++#define __NR_stty 31
++#define __NR_gtty 32
++#define __NR_access 33
++#define __NR_nice 34
++#define __NR_ftime 35
++#define __NR_sync 36
++#define __NR_kill 37
++#define __NR_rename 38
++#define __NR_mkdir 39
++#define __NR_rmdir 40
++#define __NR_dup 41
++#define __NR_pipe 42
++#define __NR_times 43
++#define __NR_prof 44
++#define __NR_brk 45
++#define __NR_setgid 46
++#define __NR_getgid 47
++#define __NR_signal 48
++#define __NR_geteuid 49
++#define __NR_getegid 50
++#define __NR_acct 51
++#define __NR_umount2 52 //vic #define __NR_phys 52
++#define __NR_lock 53
++#define __NR_ioctl 54
++#define __NR_fcntl 55
++#define __NR_mpx 56
++#define __NR_setpgid 57
++#define __NR_ulimit 58
++#define __NR_oldolduname 59
++#define __NR_umask 60
++#define __NR_chroot 61
++#define __NR_ustat 62
++#define __NR_dup2 63
++#define __NR_getppid 64
++#define __NR_getpgrp 65
++#define __NR_setsid 66
++#define __NR_sigaction 67
++#define __NR_sgetmask 68
++#define __NR_ssetmask 69
++#define __NR_setreuid 70
++#define __NR_setregid 71
++#define __NR_sigsuspend 72
++#define __NR_sigpending 73
++#define __NR_sethostname 74
++#define __NR_setrlimit 75
++#define __NR_getrlimit 76
++#define __NR_getrusage 77
++#define __NR_gettimeofday 78
++#define __NR_settimeofday 79
++#define __NR_getgroups 80
++#define __NR_setgroups 81
++#define __NR_select 82
++#define __NR_symlink 83
++#define __NR_oldlstat 84
++#define __NR_readlink 85
++#define __NR_uselib 86
++#define __NR_swapon 87
++#define __NR_reboot 88
++#define __NR_readdir 89
++#define __NR_mmap 90
++#define __NR_munmap 91
++#define __NR_truncate 92
++#define __NR_ftruncate 93
++#define __NR_fchmod 94
++#define __NR_fchown 95
++#define __NR_getpriority 96
++#define __NR_setpriority 97
++#define __NR_profil 98
++#define __NR_statfs 99
++#define __NR_fstatfs 100
++#define __NR_ioperm 101
++#define __NR_socketcall 102
++#define __NR_syslog 103
++#define __NR_setitimer 104
++#define __NR_getitimer 105
++#define __NR_stat 106
++#define __NR_lstat 107
++#define __NR_fstat 108
++#define __NR_olduname 109
++#define __NR_iopl /* 110 */ not supported
++#define __NR_vhangup 111
++#define __NR_idle /* 112 */ Obsolete
++#define __NR_vm86 /* 113 */ not supported
++#define __NR_wait4 114
++#define __NR_swapoff 115
++#define __NR_sysinfo 116
++#define __NR_ipc 117
++#define __NR_fsync 118
++#define __NR_sigreturn 119
++#define __NR_clone 120
++#define __NR_setdomainname 121
++#define __NR_uname 122
++#define __NR_cacheflush 123
++#define __NR_adjtimex 124
++#define __NR_mprotect 125
++#define __NR_sigprocmask 126
++#define __NR_create_module 127
++#define __NR_init_module 128
++#define __NR_delete_module 129
++#define __NR_get_kernel_syms 130
++#define __NR_quotactl 131
++#define __NR_getpgid 132
++#define __NR_fchdir 133
++#define __NR_bdflush 134
++#define __NR_sysfs 135
++#define __NR_personality 136
++#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
++#define __NR_setfsuid 138
++#define __NR_setfsgid 139
++#define __NR__llseek 140
++#define __NR_getdents 141
++#define __NR__newselect 142
++#define __NR_flock 143
++ /* 144 __NR_msync obsolete */
++#define __NR_readv 145
++#define __NR_writev 146
++#define __NR_getsid 147
++#define __NR_fdatasync 148
++#define __NR__sysctl 149
++#define __NR_mlock 150
++#define __NR_munlock 151
++#define __NR_mlockall 152
++#define __NR_munlockall 153
++#define __NR_sched_setparam 154
++#define __NR_sched_getparam 155
++#define __NR_sched_setscheduler 156
++#define __NR_sched_getscheduler 157
++#define __NR_sched_yield 158
++#define __NR_sched_get_priority_max 159
++#define __NR_sched_get_priority_min 160
++#define __NR_sched_rr_get_interval 161
++#define __NR_nanosleep 162
++#define __NR_mremap 163
++#define __NR_setresuid 164
++#define __NR_getresuid 165
++#define __NR_getpagesize 166
++#define __NR_query_module 167
++#define __NR_poll 168
++#define __NR_nfsservctl 169
++#define __NR_setresgid 170
++#define __NR_getresgid 171
++#define __NR_prctl 172
++#define __NR_rt_sigreturn 173
++#define __NR_rt_sigaction 174
++#define __NR_rt_sigprocmask 175
++#define __NR_rt_sigpending 176
++#define __NR_rt_sigtimedwait 177
++#define __NR_rt_sigqueueinfo 178
++#define __NR_rt_sigsuspend 179
++#define __NR_pread 180
++#define __NR_pwrite 181
++#define __NR_lchown 182
++#define __NR_getcwd 183
++#define __NR_capget 184
++#define __NR_capset 185
++#define __NR_sigaltstack 186
++#define __NR_sendfile 187
++#define __NR_getpmsg 188 /* some people actually want streams */
++#define __NR_putpmsg 189 /* some people actually want streams */
++#define __NR_vfork 190
++#define __NR_ugetrlimit 191
++#define __NR_mmap2 192
++#define __NR_truncate64 193
++#define __NR_ftruncate64 194
++#define __NR_stat64 195
++#define __NR_lstat64 196
++#define __NR_fstat64 197
++#define __NR_chown32 198
++#define __NR_getuid32 199
++#define __NR_getgid32 200
++#define __NR_geteuid32 201
++#define __NR_getegid32 202
++#define __NR_setreuid32 203
++#define __NR_setregid32 204
++#define __NR_getgroups32 205
++#define __NR_setgroups32 206
++#define __NR_fchown32 207
++#define __NR_setresuid32 208
++#define __NR_getresuid32 209
++#define __NR_setresgid32 210
++#define __NR_getresgid32 211
++#define __NR_lchown32 212
++#define __NR_setuid32 213
++#define __NR_setgid32 214
++#define __NR_setfsuid32 215
++#define __NR_setfsgid32 216
++#define __NR_pivot_root 217
++/* 218 unused */
++/* 219 unused */
++#define __NR_getdents64 220
++#define __NR_gettid 221
++#define __NR_tkill 222
++#define __NR_setxattr 223
++#define __NR_lsetxattr 224
++#define __NR_fsetxattr 225
++#define __NR_getxattr 226
++#define __NR_lgetxattr 227
++#define __NR_fgetxattr 228
++#define __NR_listxattr 229
++#define __NR_llistxattr 230
++#define __NR_flistxattr 231
++#define __NR_removexattr 232
++#define __NR_lremovexattr 233
++#define __NR_fremovexattr 234
++#define __NR_futex 235
++#define __NR_sendfile64 236
++#define __NR_mincore 237
++#define __NR_madvise 238
++#define __NR_fcntl64 239
++#define __NR_readahead 240
++#define __NR_io_setup 241
++#define __NR_io_destroy 242
++#define __NR_io_getevents 243
++#define __NR_io_submit 244
++#define __NR_io_cancel 245
++#define __NR_fadvise64 246
++#define __NR_exit_group 247
++#define __NR_lookup_dcookie 248
++#define __NR_epoll_create 249
++#define __NR_epoll_ctl 250
++#define __NR_epoll_wait 251
++#define __NR_remap_file_pages 252
++#define __NR_set_tid_address 253
++#define __NR_timer_create 254
++#define __NR_timer_settime 255
++#define __NR_timer_gettime 256
++#define __NR_timer_getoverrun 257
++#define __NR_timer_delete 258
++#define __NR_clock_settime 259
++#define __NR_clock_gettime 260
++#define __NR_clock_getres 261
++#define __NR_clock_nanosleep 262
++#define __NR_statfs64 263
++#define __NR_fstatfs64 264
++#define __NR_tgkill 265
++#define __NR_utimes 266
++#define __NR_fadvise64_64 267
++#define __NR_mbind 268
++#define __NR_get_mempolicy 269
++#define __NR_set_mempolicy 270
++#define __NR_mq_open 271
++#define __NR_mq_unlink 272
++#define __NR_mq_timedsend 273
++#define __NR_mq_timedreceive 274
++#define __NR_mq_notify 275
++#define __NR_mq_getsetattr 276
++#define __NR_waitid 277
++#define __NR_sys_setaltroot 278
++#define __NR_add_key 279
++#define __NR_request_key 280
++#define __NR_keyctl 281
++#define __NR_ioprio_set 282
++#define __NR_ioprio_get 283
++#define __NR_inotify_init 284
++#define __NR_inotify_add_watch 285
++#define __NR_inotify_rm_watch 286
++#define __NR_migrate_pages 287
++#define __NR_openat 288
++#define __NR_mkdirat 289
++#define __NR_mknodat 290
++#define __NR_fchownat 291
++#define __NR_futimesat 292
++#define __NR_fstatat64 293
++#define __NR_unlinkat 294
++#define __NR_renameat 295
++#define __NR_linkat 296
++#define __NR_symlinkat 297
++#define __NR_readlinkat 298
++#define __NR_fchmodat 299
++#define __NR_faccessat 300
++#define __NR_pselect6 301
++#define __NR_ppoll 302
++#define __NR_unshare 303
++#define __NR_set_robust_list 304
++#define __NR_get_robust_list 305
++#define __NR_splice 306
++#define __NR_sync_file_range 307
++#define __NR_tee 308
++#define __NR_vmsplice 309
++#define __NR_move_pages 310
++#define __NR_sched_setaffinity 311
++#define __NR_sched_getaffinity 312
++#define __NR_kexec_load 313
++#define __NR_getcpu 314
++#define __NR_epoll_pwait 315
++#define __NR_utimensat 316
++#define __NR_signalfd 317
++#define __NR_timerfd 318
++#define __NR_eventfd 319
++#define __NR_pread64 320
++#define __NR_pwrite64 321
++
++#ifdef __KERNEL__
++#define NR_syscalls 322
++
++#define __ARCH_WANT_IPC_PARSE_VERSION
++#define __ARCH_WANT_OLD_READDIR
++#define __ARCH_WANT_OLD_STAT
++#define __ARCH_WANT_STAT64
++#define __ARCH_WANT_SYS_ALARM
++#define __ARCH_WANT_SYS_GETHOSTNAME
++#define __ARCH_WANT_SYS_PAUSE
++#define __ARCH_WANT_SYS_SGETMASK
++#define __ARCH_WANT_SYS_SIGNAL
++#define __ARCH_WANT_SYS_TIME
++#define __ARCH_WANT_SYS_UTIME
++#define __ARCH_WANT_SYS_WAITPID
++#define __ARCH_WANT_SYS_SOCKETCALL
++#define __ARCH_WANT_SYS_FADVISE64
++#define __ARCH_WANT_SYS_GETPGRP
++#define __ARCH_WANT_SYS_LLSEEK
++#define __ARCH_WANT_SYS_NICE
++#define __ARCH_WANT_SYS_OLD_GETRLIMIT
++#define __ARCH_WANT_SYS_OLDUMOUNT
++#define __ARCH_WANT_SYS_SIGPENDING
++#define __ARCH_WANT_SYS_SIGPROCMASK
++#define __ARCH_WANT_SYS_RT_SIGACTION
++
++/*
++ * "Conditional" syscalls
++ *
++ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
++ * but it doesn't work on all toolchains, so we just do it by hand
++ */
++#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_NIOS_UNISTD_H_ */
+diff --git a/include/asm-nios2nommu/user.h b/include/asm-nios2nommu/user.h
+new file mode 100644
+index 0000000..3cdc2ba
+--- /dev/null
++++ b/include/asm-nios2nommu/user.h
+@@ -0,0 +1,112 @@
++#ifndef _NIOS2NOMMU_USER_H
++#define _NIOS2NOMMU_USER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/user.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/page.h>
++
++/* Core file format: The core file is written in such a way that gdb
++ can understand it and provide useful information to the user (under
++ linux we use the 'trad-core' bfd). There are quite a number of
++ obstacles to being able to view the contents of the floating point
++ registers, and until these are solved you will not be able to view the
++ contents of them. Actually, you can read in the core file and look at
++ the contents of the user struct to find out what the floating point
++ registers contain.
++ The actual file contents are as follows:
++ UPAGE: 1 page consisting of a user struct that tells gdb what is present
++ in the file. Directly after this is a copy of the task_struct, which
++ is currently not used by gdb, but it may come in useful at some point.
++ All of the registers are stored as part of the upage. The upage should
++ always be only one page.
++ DATA: The data area is stored. We use current->end_text to
++ current->brk to pick up all of the user variables, plus any memory
++ that may have been malloced. No attempt is made to determine if a page
++ is demand-zero or if a page is totally unused, we just cover the entire
++ range. All of the addresses are rounded in such a way that an integral
++ number of pages is written.
++ STACK: We need the stack information in order to get a meaningful
++ backtrace. We need to write the data from (esp) to
++ current->start_stack, so we round each of these off in order to be able
++ to write an integer number of pages.
++ The minimum core file size is 3 pages, or 12288 bytes.
++*/
++
++struct user_m68kfp_struct {
++ unsigned long fpregs[8*3]; /* fp0-fp7 registers */
++ unsigned long fpcntl[3]; /* fp control regs */
++};
++
++/* This is needs more work, probably should look like gdb useage */
++struct user_regs_struct {
++ long r1,r2,r3,r4,r5,r6,r7,r8;
++ long r9,r10,r11,r12,r13,r14,r15;
++ long r16,r17,r18,r19,r20,r21,r22,r23;
++ long gp;
++ long sp;
++ long ra;
++ long fp;
++ long orig_r2;
++ long estatus;
++ long status_extension;
++ long ea;
++};
++
++
++/* When the kernel dumps core, it starts by dumping the user struct -
++ this will be used by gdb to figure out where the data and stack segments
++ are within the file, and what virtual addresses to use. */
++struct user{
++/* We start with the registers, to mimic the way that "memory" is returned
++ from the ptrace(3,...) function. */
++ struct user_regs_struct regs; /* Where the registers are actually stored */
++/* ptrace does not yet supply these. Someday.... */
++ int u_fpvalid; /* True if math co-processor being used. */
++ /* for this mess. Not yet used. */
++ struct user_m68kfp_struct m68kfp; /* Math Co-processor registers. */
++/* The rest of this junk is to help gdb figure out what goes where */
++ unsigned long int u_tsize; /* Text segment size (pages). */
++ unsigned long int u_dsize; /* Data segment size (pages). */
++ unsigned long int u_ssize; /* Stack segment size (pages). */
++ unsigned long start_code; /* Starting virtual address of text. */
++ unsigned long start_stack; /* Starting virtual address of stack area.
++ This is actually the bottom of the stack,
++ the top of the stack is always found in the
++ esp register. */
++ long int signal; /* Signal that caused the core dump. */
++ int reserved; /* No longer used */
++ struct user_regs_struct *u_ar0;
++ /* Used by gdb to help find the values for */
++ /* the registers. */
++ struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */
++ unsigned long magic; /* To uniquely identify a core file */
++ char u_comm[32]; /* User command that was responsible */
++};
++#define NBPG PAGE_SIZE
++#define UPAGES 1
++#define HOST_TEXT_START_ADDR (u.start_code)
++#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
++
++#endif
+diff --git a/include/asm-nios2nommu/virtconvert.h b/include/asm-nios2nommu/virtconvert.h
+new file mode 100644
+index 0000000..89bf899
+--- /dev/null
++++ b/include/asm-nios2nommu/virtconvert.h
+@@ -0,0 +1,46 @@
++#ifndef __NIOS_VIRT_CONVERT__
++#define __NIOS_VIRT_CONVERT__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/virtconvert.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Macros used for converting between virtual and physical mappings.
++ */
++
++#ifdef __KERNEL__
++
++#include <asm/setup.h>
++#include <asm/page.h>
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#endif /*__KERNEL__ */
++#endif /*__NIOS_VIRT_CONVERT__*/
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.25.9-export-linux-aout.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.25.9-export-linux-aout.patch
new file mode 100644
index 0000000000..972fa76b06
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-2.6.25.9-export-linux-aout.patch
@@ -0,0 +1,24 @@
+[PATCH] export linux/a.out.h
+
+Export linux/a.out.h like we do for asm/a.out.h. One minor complication is
+that the interesting stuff is protected by an CONFIG_ARCH_SUPPORTS_AOUT ifdef,
+so make sure this gets defined for unifdef.
+
+Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
+---
+ include/linux/Kbuild | 2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: linux-2.6.25.6/include/linux/Kbuild
+===================================================================
+--- linux-2.6.25.6.orig/include/linux/Kbuild
++++ linux-2.6.25.6/include/linux/Kbuild
+@@ -159,6 +159,8 @@
+ header-y += videotext.h
+ header-y += x25.h
+
++UNIFDEF += -DCONFIG_ARCH_SUPPORTS_AOUT
++unifdef-y += a.out.h
+ unifdef-y += acct.h
+ unifdef-y += adb.h
+ unifdef-y += adfs_fs.h
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11-nios2nommu.patch.conditional b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11-nios2nommu.patch.conditional
new file mode 100644
index 0000000000..b8c3fff8f0
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11-nios2nommu.patch.conditional
@@ -0,0 +1,13527 @@
+--- linux/include/asm-generic/4level-fixup.h
++++ linux/include/asm-generic/4level-fixup.h
+@@ -0,0 +1,34 @@
++#ifndef _4LEVEL_FIXUP_H
++#define _4LEVEL_FIXUP_H
++
++#define __ARCH_HAS_4LEVEL_HACK
++
++#define PUD_SIZE PGDIR_SIZE
++#define PUD_MASK PGDIR_MASK
++#define PTRS_PER_PUD 1
++
++#define pud_t pgd_t
++
++#define pmd_alloc(mm, pud, address) \
++({ pmd_t *ret; \
++ if (pgd_none(*pud)) \
++ ret = __pmd_alloc(mm, pud, address); \
++ else \
++ ret = pmd_offset(pud, address); \
++ ret; \
++})
++
++#define pud_alloc(mm, pgd, address) (pgd)
++#define pud_offset(pgd, start) (pgd)
++#define pud_none(pud) 0
++#define pud_bad(pud) 0
++#define pud_present(pud) 1
++#define pud_ERROR(pud) do { } while (0)
++#define pud_clear(pud) pgd_clear(pud)
++
++#undef pud_free_tlb
++#define pud_free_tlb(tlb, x) do { } while (0)
++#define pud_free(x) do { } while (0)
++#define __pud_free_tlb(tlb, x) do { } while (0)
++
++#endif
+--- linux/include/asm-generic/bitops.h
++++ linux/include/asm-generic/bitops.h
+@@ -0,0 +1,81 @@
++#ifndef _ASM_GENERIC_BITOPS_H_
++#define _ASM_GENERIC_BITOPS_H_
++
++/*
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents. You should
++ * recode these in the native assembly language, if at all possible.
++ * To guarantee atomicity, these routines call cli() and sti() to
++ * disable interrupts while they operate. (You have to provide inline
++ * routines to cli() and sti().)
++ *
++ * Also note, these routines assume that you have 32 bit longs.
++ * You will have to change this if you are trying to port Linux to the
++ * Alpha architecture or to a Cray. :-)
++ *
++ * C language equivalents written by Theodore Ts'o, 9/26/92
++ */
++
++extern __inline__ int set_bit(int nr,long * addr)
++{
++ int mask, retval;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ cli();
++ retval = (mask & *addr) != 0;
++ *addr |= mask;
++ sti();
++ return retval;
++}
++
++extern __inline__ int clear_bit(int nr, long * addr)
++{
++ int mask, retval;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ cli();
++ retval = (mask & *addr) != 0;
++ *addr &= ~mask;
++ sti();
++ return retval;
++}
++
++extern __inline__ int test_bit(int nr, const unsigned long * addr)
++{
++ int mask;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ return ((mask & *addr) != 0);
++}
++
++/*
++ * fls: find last bit set.
++ */
++
++#define fls(x) generic_fls(x)
++
++#ifdef __KERNEL__
++
++/*
++ * ffs: find first bit set. This is defined the same way as
++ * the libc and compiler builtin ffs routines, therefore
++ * differs in spirit from the above ffz (man ffs).
++ */
++
++#define ffs(x) generic_ffs(x)
++
++/*
++ * hweightN: returns the hamming weight (i.e. the number
++ * of bits set) of a N-bit word
++ */
++
++#define hweight32(x) generic_hweight32(x)
++#define hweight16(x) generic_hweight16(x)
++#define hweight8(x) generic_hweight8(x)
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_GENERIC_BITOPS_H */
+--- linux/include/asm-generic/bug.h
++++ linux/include/asm-generic/bug.h
+@@ -0,0 +1,34 @@
++#ifndef _ASM_GENERIC_BUG_H
++#define _ASM_GENERIC_BUG_H
++
++#include <linux/compiler.h>
++// #include <linux/config.h>
++
++#ifndef HAVE_ARCH_BUG
++#define BUG() do { \
++ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
++ panic("BUG!"); \
++} while (0)
++#endif
++
++#ifndef HAVE_ARCH_PAGE_BUG
++#define PAGE_BUG(page) do { \
++ printk("page BUG for page at %p\n", page); \
++ BUG(); \
++} while (0)
++#endif
++
++#ifndef HAVE_ARCH_BUG_ON
++#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
++#endif
++
++#ifndef HAVE_ARCH_WARN_ON
++#define WARN_ON(condition) do { \
++ if (unlikely((condition)!=0)) { \
++ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
++ dump_stack(); \
++ } \
++} while (0)
++#endif
++
++#endif
+--- linux/include/asm-generic/cpumask_arith.h
++++ linux/include/asm-generic/cpumask_arith.h
+@@ -0,0 +1,49 @@
++#ifndef __ASM_GENERIC_CPUMASK_ARITH_H
++#define __ASM_GENERIC_CPUMASK_ARITH_H
++
++/*
++ * Arithmetic type -based cpu bitmaps. A single unsigned long is used
++ * to contain the whole cpu bitmap.
++ */
++
++#define cpu_set(cpu, map) set_bit(cpu, &(map))
++#define cpu_clear(cpu, map) clear_bit(cpu, &(map))
++#define cpu_isset(cpu, map) test_bit(cpu, &(map))
++#define cpu_test_and_set(cpu, map) test_and_set_bit(cpu, &(map))
++
++#define cpus_and(dst,src1,src2) do { dst = (src1) & (src2); } while (0)
++#define cpus_or(dst,src1,src2) do { dst = (src1) | (src2); } while (0)
++#define cpus_clear(map) do { map = 0; } while (0)
++#define cpus_complement(map) do { map = ~(map); } while (0)
++#define cpus_equal(map1, map2) ((map1) == (map2))
++#define cpus_empty(map) ((map) == 0)
++#define cpus_addr(map) (&(map))
++
++#if BITS_PER_LONG == 32
++#define cpus_weight(map) hweight32(map)
++#elif BITS_PER_LONG == 64
++#define cpus_weight(map) hweight64(map)
++#endif
++
++#define cpus_shift_right(dst, src, n) do { dst = (src) >> (n); } while (0)
++#define cpus_shift_left(dst, src, n) do { dst = (src) << (n); } while (0)
++
++#define any_online_cpu(map) \
++({ \
++ cpumask_t __tmp__; \
++ cpus_and(__tmp__, map, cpu_online_map); \
++ __tmp__ ? first_cpu(__tmp__) : NR_CPUS; \
++})
++
++#define CPU_MASK_ALL (~((cpumask_t)0) >> (8*sizeof(cpumask_t) - NR_CPUS))
++#define CPU_MASK_NONE ((cpumask_t)0)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce(map) ((unsigned long)(map))
++#define cpus_promote(map) ({ map; })
++#define cpumask_of_cpu(cpu) ({ ((cpumask_t)1) << (cpu); })
++
++#define first_cpu(map) __ffs(map)
++#define next_cpu(cpu, map) find_next_bit(&(map), NR_CPUS, cpu + 1)
++
++#endif /* __ASM_GENERIC_CPUMASK_ARITH_H */
+--- linux/include/asm-generic/cpumask_array.h
++++ linux/include/asm-generic/cpumask_array.h
+@@ -0,0 +1,54 @@
++#ifndef __ASM_GENERIC_CPUMASK_ARRAY_H
++#define __ASM_GENERIC_CPUMASK_ARRAY_H
++
++/*
++ * Array-based cpu bitmaps. An array of unsigned longs is used to contain
++ * the bitmap, and then contained in a structure so it may be passed by
++ * value.
++ */
++
++#define CPU_ARRAY_SIZE BITS_TO_LONGS(NR_CPUS)
++
++#define cpu_set(cpu, map) set_bit(cpu, (map).mask)
++#define cpu_clear(cpu, map) clear_bit(cpu, (map).mask)
++#define cpu_isset(cpu, map) test_bit(cpu, (map).mask)
++#define cpu_test_and_set(cpu, map) test_and_set_bit(cpu, (map).mask)
++
++#define cpus_and(dst,src1,src2) bitmap_and((dst).mask,(src1).mask, (src2).mask, NR_CPUS)
++#define cpus_or(dst,src1,src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, NR_CPUS)
++#define cpus_clear(map) bitmap_clear((map).mask, NR_CPUS)
++#define cpus_complement(map) bitmap_complement((map).mask, NR_CPUS)
++#define cpus_equal(map1, map2) bitmap_equal((map1).mask, (map2).mask, NR_CPUS)
++#define cpus_empty(map) bitmap_empty(map.mask, NR_CPUS)
++#define cpus_addr(map) ((map).mask)
++#define cpus_weight(map) bitmap_weight((map).mask, NR_CPUS)
++#define cpus_shift_right(d, s, n) bitmap_shift_right((d).mask, (s).mask, n, NR_CPUS)
++#define cpus_shift_left(d, s, n) bitmap_shift_left((d).mask, (s).mask, n, NR_CPUS)
++#define first_cpu(map) find_first_bit((map).mask, NR_CPUS)
++#define next_cpu(cpu, map) find_next_bit((map).mask, NR_CPUS, cpu + 1)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce(map) ((map).mask[0])
++#define cpus_promote(map) ({ cpumask_t __cpu_mask = CPU_MASK_NONE;\
++ __cpu_mask.mask[0] = map; \
++ __cpu_mask; \
++ })
++#define cpumask_of_cpu(cpu) ({ cpumask_t __cpu_mask = CPU_MASK_NONE;\
++ cpu_set(cpu, __cpu_mask); \
++ __cpu_mask; \
++ })
++#define any_online_cpu(map) \
++({ \
++ cpumask_t __tmp__; \
++ cpus_and(__tmp__, map, cpu_online_map); \
++ find_first_bit(__tmp__.mask, NR_CPUS); \
++})
++
++
++/*
++ * um, these need to be usable as static initializers
++ */
++#define CPU_MASK_ALL { {[0 ... CPU_ARRAY_SIZE-1] = ~0UL} }
++#define CPU_MASK_NONE { {[0 ... CPU_ARRAY_SIZE-1] = 0UL} }
++
++#endif /* __ASM_GENERIC_CPUMASK_ARRAY_H */
+--- linux/include/asm-generic/cpumask_const_reference.h
++++ linux/include/asm-generic/cpumask_const_reference.h
+@@ -0,0 +1,29 @@
++#ifndef __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H
++#define __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H
++
++struct cpumask_ref {
++ const cpumask_t *val;
++};
++
++typedef const struct cpumask_ref cpumask_const_t;
++
++#define mk_cpumask_const(map) ((cpumask_const_t){ &(map) })
++#define cpu_isset_const(cpu, map) cpu_isset(cpu, *(map).val)
++
++#define cpus_and_const(dst,src1,src2) cpus_and(dst,*(src1).val,*(src2).val)
++#define cpus_or_const(dst,src1,src2) cpus_or(dst,*(src1).val,*(src2).val)
++
++#define cpus_equal_const(map1, map2) cpus_equal(*(map1).val, *(map2).val)
++
++#define cpus_copy_const(map1, map2) bitmap_copy((map1).mask, (map2).val->mask, NR_CPUS)
++
++#define cpus_empty_const(map) cpus_empty(*(map).val)
++#define cpus_weight_const(map) cpus_weight(*(map).val)
++#define first_cpu_const(map) first_cpu(*(map).val)
++#define next_cpu_const(cpu, map) next_cpu(cpu, *(map).val)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce_const(map) cpus_coerce(*(map).val)
++#define any_online_cpu_const(map) any_online_cpu(*(map).val)
++
++#endif /* __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H */
+--- linux/include/asm-generic/cpumask_const_value.h
++++ linux/include/asm-generic/cpumask_const_value.h
+@@ -0,0 +1,21 @@
++#ifndef __ASM_GENERIC_CPUMASK_CONST_VALUE_H
++#define __ASM_GENERIC_CPUMASK_CONST_VALUE_H
++
++typedef const cpumask_t cpumask_const_t;
++
++#define mk_cpumask_const(map) (map)
++#define cpu_isset_const(cpu, map) cpu_isset(cpu, map)
++#define cpus_and_const(dst,src1,src2) cpus_and(dst, src1, src2)
++#define cpus_or_const(dst,src1,src2) cpus_or(dst, src1, src2)
++#define cpus_equal_const(map1, map2) cpus_equal(map1, map2)
++#define cpus_empty_const(map) cpus_empty(map)
++#define cpus_copy_const(map1, map2) do { map1 = (cpumask_t)map2; } while (0)
++#define cpus_weight_const(map) cpus_weight(map)
++#define first_cpu_const(map) first_cpu(map)
++#define next_cpu_const(cpu, map) next_cpu(cpu, map)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce_const(map) cpus_coerce(map)
++#define any_online_cpu_const(map) any_online_cpu(map)
++
++#endif /* __ASM_GENERIC_CPUMASK_CONST_VALUE_H */
+--- linux/include/asm-generic/cpumask.h
++++ linux/include/asm-generic/cpumask.h
+@@ -0,0 +1,40 @@
++#ifndef __ASM_GENERIC_CPUMASK_H
++#define __ASM_GENERIC_CPUMASK_H
++
++// #include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/types.h>
++#include <linux/bitmap.h>
++
++#if NR_CPUS > BITS_PER_LONG && NR_CPUS != 1
++#define CPU_ARRAY_SIZE BITS_TO_LONGS(NR_CPUS)
++
++struct cpumask
++{
++ unsigned long mask[CPU_ARRAY_SIZE];
++};
++
++typedef struct cpumask cpumask_t;
++
++#else
++typedef unsigned long cpumask_t;
++#endif
++
++#ifdef CONFIG_SMP
++#if NR_CPUS > BITS_PER_LONG
++#include <asm-generic/cpumask_array.h>
++#else
++#include <asm-generic/cpumask_arith.h>
++#endif
++#else
++#include <asm-generic/cpumask_up.h>
++#endif
++
++#if NR_CPUS <= 4*BITS_PER_LONG
++#include <asm-generic/cpumask_const_value.h>
++#else
++#include <asm-generic/cpumask_const_reference.h>
++#endif
++
++#endif /* __ASM_GENERIC_CPUMASK_H */
+--- linux/include/asm-generic/cpumask_up.h
++++ linux/include/asm-generic/cpumask_up.h
+@@ -0,0 +1,59 @@
++#ifndef __ASM_GENERIC_CPUMASK_UP_H
++#define __ASM_GENERIC_CPUMASK_UP_H
++
++#define cpus_coerce(map) (map)
++
++#define cpu_set(cpu, map) do { (void)(cpu); cpus_coerce(map) = 1UL; } while (0)
++#define cpu_clear(cpu, map) do { (void)(cpu); cpus_coerce(map) = 0UL; } while (0)
++#define cpu_isset(cpu, map) ((void)(cpu), cpus_coerce(map) != 0UL)
++#define cpu_test_and_set(cpu, map) ((void)(cpu), test_and_set_bit(0, &(map)))
++
++#define cpus_and(dst, src1, src2) \
++ do { \
++ if (cpus_coerce(src1) && cpus_coerce(src2)) \
++ cpus_coerce(dst) = 1UL; \
++ else \
++ cpus_coerce(dst) = 0UL; \
++ } while (0)
++
++#define cpus_or(dst, src1, src2) \
++ do { \
++ if (cpus_coerce(src1) || cpus_coerce(src2)) \
++ cpus_coerce(dst) = 1UL; \
++ else \
++ cpus_coerce(dst) = 0UL; \
++ } while (0)
++
++#define cpus_clear(map) do { cpus_coerce(map) = 0UL; } while (0)
++
++#define cpus_complement(map) \
++ do { \
++ cpus_coerce(map) = !cpus_coerce(map); \
++ } while (0)
++
++#define cpus_equal(map1, map2) (cpus_coerce(map1) == cpus_coerce(map2))
++#define cpus_empty(map) (cpus_coerce(map) == 0UL)
++#define cpus_addr(map) (&(map))
++#define cpus_weight(map) (cpus_coerce(map) ? 1UL : 0UL)
++#define cpus_shift_right(d, s, n) do { cpus_coerce(d) = 0UL; } while (0)
++#define cpus_shift_left(d, s, n) do { cpus_coerce(d) = 0UL; } while (0)
++#define first_cpu(map) (cpus_coerce(map) ? 0 : 1)
++#define next_cpu(cpu, map) 1
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_promote(map) \
++ ({ \
++ cpumask_t __tmp__; \
++ cpus_coerce(__tmp__) = map; \
++ __tmp__; \
++ })
++#define cpumask_of_cpu(cpu) ((void)(cpu), cpus_promote(1))
++#define any_online_cpu(map) (cpus_coerce(map) ? 0 : 1)
++
++/*
++ * um, these need to be usable as static initializers
++ */
++#define CPU_MASK_ALL 1UL
++#define CPU_MASK_NONE 0UL
++
++#endif /* __ASM_GENERIC_CPUMASK_UP_H */
+--- linux/include/asm-generic/cputime.h
++++ linux/include/asm-generic/cputime.h
+@@ -0,0 +1,64 @@
++#ifndef _ASM_GENERIC_CPUTIME_H
++#define _ASM_GENERIC_CPUTIME_H
++
++#include <linux/time.h>
++#include <linux/jiffies.h>
++
++typedef unsigned long cputime_t;
++
++#define cputime_zero (0UL)
++#define cputime_max ((~0UL >> 1) - 1)
++#define cputime_add(__a, __b) ((__a) + (__b))
++#define cputime_sub(__a, __b) ((__a) - (__b))
++#define cputime_eq(__a, __b) ((__a) == (__b))
++#define cputime_gt(__a, __b) ((__a) > (__b))
++#define cputime_ge(__a, __b) ((__a) >= (__b))
++#define cputime_lt(__a, __b) ((__a) < (__b))
++#define cputime_le(__a, __b) ((__a) <= (__b))
++#define cputime_to_jiffies(__ct) (__ct)
++#define jiffies_to_cputime(__hz) (__hz)
++
++typedef u64 cputime64_t;
++
++#define cputime64_zero (0ULL)
++#define cputime64_add(__a, __b) ((__a) + (__b))
++#define cputime64_to_jiffies64(__ct) (__ct)
++#define cputime_to_cputime64(__ct) ((u64) __ct)
++
++
++/*
++ * Convert cputime to milliseconds and back.
++ */
++#define cputime_to_msecs(__ct) jiffies_to_msecs(__ct)
++#define msecs_to_cputime(__msecs) msecs_to_jiffies(__msecs)
++
++/*
++ * Convert cputime to seconds and back.
++ */
++#define cputime_to_secs(jif) ((jif) / HZ)
++#define secs_to_cputime(sec) ((sec) * HZ)
++
++/*
++ * Convert cputime to timespec and back.
++ */
++#define timespec_to_cputime(__val) timespec_to_jiffies(__val)
++#define cputime_to_timespec(__ct,__val) jiffies_to_timespec(__ct,__val)
++
++/*
++ * Convert cputime to timeval and back.
++ */
++#define timeval_to_cputime(__val) timeval_to_jiffies(__val)
++#define cputime_to_timeval(__ct,__val) jiffies_to_timeval(__ct,__val)
++
++/*
++ * Convert cputime to clock and back.
++ */
++#define cputime_to_clock_t(__ct) jiffies_to_clock_t(__ct)
++#define clock_t_to_cputime(__x) clock_t_to_jiffies(__x)
++
++/*
++ * Convert cputime64 to clock.
++ */
++#define cputime64_to_clock_t(__ct) jiffies_64_to_clock_t(__ct)
++
++#endif
+--- linux/include/asm-generic/div64.h
++++ linux/include/asm-generic/div64.h
+@@ -0,0 +1,58 @@
++#ifndef _ASM_GENERIC_DIV64_H
++#define _ASM_GENERIC_DIV64_H
++/*
++ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
++ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
++ *
++ * The semantics of do_div() are:
++ *
++ * uint32_t do_div(uint64_t *n, uint32_t base)
++ * {
++ * uint32_t remainder = *n % base;
++ * *n = *n / base;
++ * return remainder;
++ * }
++ *
++ * NOTE: macro parameter n is evaluated multiple times,
++ * beware of side effects!
++ */
++
++#include <linux/types.h>
++#include <linux/compiler.h>
++
++#if BITS_PER_LONG == 64
++
++# define do_div(n,base) ({ \
++ uint32_t __base = (base); \
++ uint32_t __rem; \
++ __rem = ((uint64_t)(n)) % __base; \
++ (n) = ((uint64_t)(n)) / __base; \
++ __rem; \
++ })
++
++#elif BITS_PER_LONG == 32
++
++extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
++
++/* The unnecessary pointer compare is there
++ * to check for type safety (n must be 64bit)
++ */
++# define do_div(n,base) ({ \
++ uint32_t __base = (base); \
++ uint32_t __rem; \
++ (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
++ if (likely(((n) >> 32) == 0)) { \
++ __rem = (uint32_t)(n) % __base; \
++ (n) = (uint32_t)(n) / __base; \
++ } else \
++ __rem = __div64_32(&(n), __base); \
++ __rem; \
++ })
++
++#else /* BITS_PER_LONG == ?? */
++
++# error do_div() does not yet support the C64
++
++#endif /* BITS_PER_LONG */
++
++#endif /* _ASM_GENERIC_DIV64_H */
+--- linux/include/asm-generic/dma-mapping-broken.h
++++ linux/include/asm-generic/dma-mapping-broken.h
+@@ -0,0 +1,22 @@
++#ifndef _ASM_GENERIC_DMA_MAPPING_H
++#define _ASM_GENERIC_DMA_MAPPING_H
++
++/* This is used for archs that do not support DMA */
++
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG();
++ return NULL;
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++#endif /* _ASM_GENERIC_DMA_MAPPING_H */
+--- linux/include/asm-generic/dma-mapping.h
++++ linux/include/asm-generic/dma-mapping.h
+@@ -0,0 +1,309 @@
++/* Copyright (C) 2002 by James.Bottomley@HansenPartnership.com
++ *
++ * Implements the generic device dma API via the existing pci_ one
++ * for unconverted architectures
++ */
++
++#ifndef _ASM_GENERIC_DMA_MAPPING_H
++#define _ASM_GENERIC_DMA_MAPPING_H
++
++// #include <linux/config.h>
++
++#ifdef CONFIG_PCI
++
++/* we implement the API below in terms of the existing PCI one,
++ * so include it */
++#include <linux/pci.h>
++/* need struct page definitions */
++#include <linux/mm.h>
++
++static inline int
++dma_supported(struct device *dev, u64 mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_dma_supported(to_pci_dev(dev), mask);
++}
++
++static inline int
++dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
++}
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
++}
++
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
++}
++
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
++}
++
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
++}
++
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
++}
++
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline int
++dma_mapping_error(dma_addr_t dma_addr)
++{
++ return pci_dma_mapping_error(dma_addr);
++}
++
++
++#else
++
++static inline int
++dma_supported(struct device *dev, u64 mask)
++{
++ return 0;
++}
++
++static inline int
++dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ BUG();
++ return 0;
++}
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG();
++ return NULL;
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline int
++dma_error(dma_addr_t dma_addr)
++{
++ return 0;
++}
++
++#endif
++
++/* Now for the API extensions over the pci_ one */
++
++#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
++#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
++#define dma_is_consistent(d) (1)
++
++static inline int
++dma_get_cache_alignment(void)
++{
++ /* no easy way to get cache size on all processors, so return
++ * the maximum possible, to be safe */
++ return (1 << L1_CACHE_SHIFT_MAX);
++}
++
++static inline void
++dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ /* just sync everything, that's all the pci API can do */
++ dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
++}
++
++static inline void
++dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ /* just sync everything, that's all the pci API can do */
++ dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
++}
++
++static inline void
++dma_cache_sync(void *vaddr, size_t size,
++ enum dma_data_direction direction)
++{
++ /* could define this in terms of the dma_cache ... operations,
++ * but if you get this on a platform, you should convert the platform
++ * to using the generic device DMA API */
++ BUG();
++}
++
++#endif
++
+--- linux/include/asm-generic/errno-base.h
++++ linux/include/asm-generic/errno-base.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_GENERIC_ERRNO_BASE_H
++#define _ASM_GENERIC_ERRNO_BASE_H
++
++#define EPERM 1 /* Operation not permitted */
++#define ENOENT 2 /* No such file or directory */
++#define ESRCH 3 /* No such process */
++#define EINTR 4 /* Interrupted system call */
++#define EIO 5 /* I/O error */
++#define ENXIO 6 /* No such device or address */
++#define E2BIG 7 /* Argument list too long */
++#define ENOEXEC 8 /* Exec format error */
++#define EBADF 9 /* Bad file number */
++#define ECHILD 10 /* No child processes */
++#define EAGAIN 11 /* Try again */
++#define ENOMEM 12 /* Out of memory */
++#define EACCES 13 /* Permission denied */
++#define EFAULT 14 /* Bad address */
++#define ENOTBLK 15 /* Block device required */
++#define EBUSY 16 /* Device or resource busy */
++#define EEXIST 17 /* File exists */
++#define EXDEV 18 /* Cross-device link */
++#define ENODEV 19 /* No such device */
++#define ENOTDIR 20 /* Not a directory */
++#define EISDIR 21 /* Is a directory */
++#define EINVAL 22 /* Invalid argument */
++#define ENFILE 23 /* File table overflow */
++#define EMFILE 24 /* Too many open files */
++#define ENOTTY 25 /* Not a typewriter */
++#define ETXTBSY 26 /* Text file busy */
++#define EFBIG 27 /* File too large */
++#define ENOSPC 28 /* No space left on device */
++#define ESPIPE 29 /* Illegal seek */
++#define EROFS 30 /* Read-only file system */
++#define EMLINK 31 /* Too many links */
++#define EPIPE 32 /* Broken pipe */
++#define EDOM 33 /* Math argument out of domain of func */
++#define ERANGE 34 /* Math result not representable */
++
++#endif
+--- linux/include/asm-generic/errno.h
++++ linux/include/asm-generic/errno.h
+@@ -0,0 +1,105 @@
++#ifndef _ASM_GENERIC_ERRNO_H
++#define _ASM_GENERIC_ERRNO_H
++
++#include <asm-generic/errno-base.h>
++
++#define EDEADLK 35 /* Resource deadlock would occur */
++#define ENAMETOOLONG 36 /* File name too long */
++#define ENOLCK 37 /* No record locks available */
++#define ENOSYS 38 /* Function not implemented */
++#define ENOTEMPTY 39 /* Directory not empty */
++#define ELOOP 40 /* Too many symbolic links encountered */
++#define EWOULDBLOCK EAGAIN /* Operation would block */
++#define ENOMSG 42 /* No message of desired type */
++#define EIDRM 43 /* Identifier removed */
++#define ECHRNG 44 /* Channel number out of range */
++#define EL2NSYNC 45 /* Level 2 not synchronized */
++#define EL3HLT 46 /* Level 3 halted */
++#define EL3RST 47 /* Level 3 reset */
++#define ELNRNG 48 /* Link number out of range */
++#define EUNATCH 49 /* Protocol driver not attached */
++#define ENOCSI 50 /* No CSI structure available */
++#define EL2HLT 51 /* Level 2 halted */
++#define EBADE 52 /* Invalid exchange */
++#define EBADR 53 /* Invalid request descriptor */
++#define EXFULL 54 /* Exchange full */
++#define ENOANO 55 /* No anode */
++#define EBADRQC 56 /* Invalid request code */
++#define EBADSLT 57 /* Invalid slot */
++
++#define EDEADLOCK EDEADLK
++
++#define EBFONT 59 /* Bad font file format */
++#define ENOSTR 60 /* Device not a stream */
++#define ENODATA 61 /* No data available */
++#define ETIME 62 /* Timer expired */
++#define ENOSR 63 /* Out of streams resources */
++#define ENONET 64 /* Machine is not on the network */
++#define ENOPKG 65 /* Package not installed */
++#define EREMOTE 66 /* Object is remote */
++#define ENOLINK 67 /* Link has been severed */
++#define EADV 68 /* Advertise error */
++#define ESRMNT 69 /* Srmount error */
++#define ECOMM 70 /* Communication error on send */
++#define EPROTO 71 /* Protocol error */
++#define EMULTIHOP 72 /* Multihop attempted */
++#define EDOTDOT 73 /* RFS specific error */
++#define EBADMSG 74 /* Not a data message */
++#define EOVERFLOW 75 /* Value too large for defined data type */
++#define ENOTUNIQ 76 /* Name not unique on network */
++#define EBADFD 77 /* File descriptor in bad state */
++#define EREMCHG 78 /* Remote address changed */
++#define ELIBACC 79 /* Can not access a needed shared library */
++#define ELIBBAD 80 /* Accessing a corrupted shared library */
++#define ELIBSCN 81 /* .lib section in a.out corrupted */
++#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
++#define ELIBEXEC 83 /* Cannot exec a shared library directly */
++#define EILSEQ 84 /* Illegal byte sequence */
++#define ERESTART 85 /* Interrupted system call should be restarted */
++#define ESTRPIPE 86 /* Streams pipe error */
++#define EUSERS 87 /* Too many users */
++#define ENOTSOCK 88 /* Socket operation on non-socket */
++#define EDESTADDRREQ 89 /* Destination address required */
++#define EMSGSIZE 90 /* Message too long */
++#define EPROTOTYPE 91 /* Protocol wrong type for socket */
++#define ENOPROTOOPT 92 /* Protocol not available */
++#define EPROTONOSUPPORT 93 /* Protocol not supported */
++#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
++#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
++#define EPFNOSUPPORT 96 /* Protocol family not supported */
++#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
++#define EADDRINUSE 98 /* Address already in use */
++#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
++#define ENETDOWN 100 /* Network is down */
++#define ENETUNREACH 101 /* Network is unreachable */
++#define ENETRESET 102 /* Network dropped connection because of reset */
++#define ECONNABORTED 103 /* Software caused connection abort */
++#define ECONNRESET 104 /* Connection reset by peer */
++#define ENOBUFS 105 /* No buffer space available */
++#define EISCONN 106 /* Transport endpoint is already connected */
++#define ENOTCONN 107 /* Transport endpoint is not connected */
++#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
++#define ETOOMANYREFS 109 /* Too many references: cannot splice */
++#define ETIMEDOUT 110 /* Connection timed out */
++#define ECONNREFUSED 111 /* Connection refused */
++#define EHOSTDOWN 112 /* Host is down */
++#define EHOSTUNREACH 113 /* No route to host */
++#define EALREADY 114 /* Operation already in progress */
++#define EINPROGRESS 115 /* Operation now in progress */
++#define ESTALE 116 /* Stale NFS file handle */
++#define EUCLEAN 117 /* Structure needs cleaning */
++#define ENOTNAM 118 /* Not a XENIX named type file */
++#define ENAVAIL 119 /* No XENIX semaphores available */
++#define EISNAM 120 /* Is a named type file */
++#define EREMOTEIO 121 /* Remote I/O error */
++#define EDQUOT 122 /* Quota exceeded */
++
++#define ENOMEDIUM 123 /* No medium found */
++#define EMEDIUMTYPE 124 /* Wrong medium type */
++#define ECANCELED 125 /* Operation Canceled */
++#define ENOKEY 126 /* Required key not available */
++#define EKEYEXPIRED 127 /* Key has expired */
++#define EKEYREVOKED 128 /* Key has been revoked */
++#define EKEYREJECTED 129 /* Key was rejected by service */
++
++#endif
+--- linux/include/asm-generic/hdreg.h
++++ linux/include/asm-generic/hdreg.h
+@@ -0,0 +1,8 @@
++#warning <asm/hdreg.h> is obsolete, please do not use it
++
++#ifndef __ASM_GENERIC_HDREG_H
++#define __ASM_GENERIC_HDREG_H
++
++typedef unsigned long ide_ioreg_t;
++
++#endif /* __ASM_GENERIC_HDREG_H */
+--- linux/include/asm-generic/ide_iops.h
++++ linux/include/asm-generic/ide_iops.h
+@@ -0,0 +1,38 @@
++/* Generic I/O and MEMIO string operations. */
++
++#define __ide_insw insw
++#define __ide_insl insl
++#define __ide_outsw outsw
++#define __ide_outsl outsl
++
++static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ *(u16 *)addr = readw(port);
++ addr += 2;
++ }
++}
++
++static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ *(u32 *)addr = readl(port);
++ addr += 4;
++ }
++}
++
++static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ writew(*(u16 *)addr, port);
++ addr += 2;
++ }
++}
++
++static __inline__ void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
++{
++ while (count--) {
++ writel(*(u32 *)addr, port);
++ addr += 4;
++ }
++}
+--- linux/include/asm-generic/iomap.h
++++ linux/include/asm-generic/iomap.h
+@@ -0,0 +1,63 @@
++#ifndef __GENERIC_IO_H
++#define __GENERIC_IO_H
++
++#include <linux/linkage.h>
++
++/*
++ * These are the "generic" interfaces for doing new-style
++ * memory-mapped or PIO accesses. Architectures may do
++ * their own arch-optimized versions, these just act as
++ * wrappers around the old-style IO register access functions:
++ * read[bwl]/write[bwl]/in[bwl]/out[bwl]
++ *
++ * Don't include this directly, include it from <asm/io.h>.
++ */
++
++/*
++ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
++ * access or a MMIO access, these functions don't care. The info is
++ * encoded in the hardware mapping set up by the mapping functions
++ * (or the cookie itself, depending on implementation and hw).
++ *
++ * The generic routines just encode the PIO/MMIO as part of the
++ * cookie, and coldly assume that the MMIO IO mappings are not
++ * in the low address range. Architectures for which this is not
++ * true can't use this generic implementation.
++ */
++extern unsigned int fastcall ioread8(void __iomem *);
++extern unsigned int fastcall ioread16(void __iomem *);
++extern unsigned int fastcall ioread32(void __iomem *);
++
++extern void fastcall iowrite8(u8, void __iomem *);
++extern void fastcall iowrite16(u16, void __iomem *);
++extern void fastcall iowrite32(u32, void __iomem *);
++
++/*
++ * "string" versions of the above. Note that they
++ * use native byte ordering for the accesses (on
++ * the assumption that IO and memory agree on a
++ * byte order, and CPU byteorder is irrelevant).
++ *
++ * They do _not_ update the port address. If you
++ * want MMIO that copies stuff laid out in MMIO
++ * memory across multiple ports, use "memcpy_toio()"
++ * and friends.
++ */
++extern void fastcall ioread8_rep(void __iomem *port, void *buf, unsigned long count);
++extern void fastcall ioread16_rep(void __iomem *port, void *buf, unsigned long count);
++extern void fastcall ioread32_rep(void __iomem *port, void *buf, unsigned long count);
++
++extern void fastcall iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
++extern void fastcall iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
++extern void fastcall iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
++
++/* Create a virtual mapping cookie for an IO port range */
++extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
++extern void ioport_unmap(void __iomem *);
++
++/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
++struct pci_dev;
++extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
++extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
++
++#endif
+--- linux/include/asm-generic/local.h
++++ linux/include/asm-generic/local.h
+@@ -0,0 +1,118 @@
++#ifndef _ASM_GENERIC_LOCAL_H
++#define _ASM_GENERIC_LOCAL_H
++
++// #include <linux/config.h>
++#include <linux/percpu.h>
++#include <linux/hardirq.h>
++#include <asm/types.h>
++
++/* An unsigned long type for operations which are atomic for a single
++ * CPU. Usually used in combination with per-cpu variables. */
++
++#if BITS_PER_LONG == 32
++/* Implement in terms of atomics. */
++
++/* Don't use typedef: don't want them to be mixed with atomic_t's. */
++typedef struct
++{
++ atomic_t a;
++} local_t;
++
++#define LOCAL_INIT(i) { ATOMIC_INIT(i) }
++
++#define local_read(l) ((unsigned long)atomic_read(&(l)->a))
++#define local_set(l,i) atomic_set((&(l)->a),(i))
++#define local_inc(l) atomic_inc(&(l)->a)
++#define local_dec(l) atomic_dec(&(l)->a)
++#define local_add(i,l) atomic_add((i),(&(l)->a))
++#define local_sub(i,l) atomic_sub((i),(&(l)->a))
++
++/* Non-atomic variants, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well. */
++#define __local_inc(l) local_set((l), local_read(l) + 1)
++#define __local_dec(l) local_set((l), local_read(l) - 1)
++#define __local_add(i,l) local_set((l), local_read(l) + (i))
++#define __local_sub(i,l) local_set((l), local_read(l) - (i))
++
++#else /* ... can't use atomics. */
++/* Implement in terms of three variables.
++ Another option would be to use local_irq_save/restore. */
++
++typedef struct
++{
++ /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
++ unsigned long v[3];
++} local_t;
++
++#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
++
++#define LOCAL_INIT(i) { { (i), 0, 0 } }
++
++static inline unsigned long local_read(local_t *l)
++{
++ return l->v[0] + l->v[1] + l->v[2];
++}
++
++static inline void local_set(local_t *l, unsigned long v)
++{
++ l->v[0] = v;
++ l->v[1] = l->v[2] = 0;
++}
++
++static inline void local_inc(local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l)++;
++ preempt_enable();
++}
++
++static inline void local_dec(local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l)--;
++ preempt_enable();
++}
++
++static inline void local_add(unsigned long v, local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l) += v;
++ preempt_enable();
++}
++
++static inline void local_sub(unsigned long v, local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l) -= v;
++ preempt_enable();
++}
++
++/* Non-atomic variants, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well. */
++#define __local_inc(l) ((l)->v[0]++)
++#define __local_dec(l) ((l)->v[0]--)
++#define __local_add(i,l) ((l)->v[0] += (i))
++#define __local_sub(i,l) ((l)->v[0] -= (i))
++
++#endif /* Non-atomic implementation */
++
++/* Use these for per-cpu local_t variables: on some archs they are
++ * much more efficient than these naive implementations. Note they take
++ * a variable (eg. mystruct.foo), not an address.
++ */
++#define cpu_local_read(v) local_read(&__get_cpu_var(v))
++#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
++#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
++#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
++#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
++#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
++
++/* Non-atomic increments, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well.
++ */
++#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v))
++#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v))
++#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v))
++#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v))
++
++#endif /* _ASM_GENERIC_LOCAL_H */
+--- linux/include/asm-generic/pci-dma-compat.h
++++ linux/include/asm-generic/pci-dma-compat.h
+@@ -0,0 +1,107 @@
++/* include this file if the platform implements the dma_ DMA Mapping API
++ * and wants to provide the pci_ DMA Mapping API in terms of it */
++
++#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
++#define _ASM_GENERIC_PCI_DMA_COMPAT_H
++
++#include <linux/dma-mapping.h>
++
++/* note pci_set_dma_mask isn't here, since it's a public function
++ * exported from drivers/pci, use dma_supported instead */
++
++static inline int
++pci_dma_supported(struct pci_dev *hwdev, u64 mask)
++{
++ return dma_supported(hwdev == NULL ? NULL : &hwdev->dev, mask);
++}
++
++static inline void *
++pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
++ dma_addr_t *dma_handle)
++{
++ return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
++}
++
++static inline void
++pci_free_consistent(struct pci_dev *hwdev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
++}
++
++static inline dma_addr_t
++pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
++{
++ return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
++ size_t size, int direction)
++{
++ dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
++}
++
++static inline dma_addr_t
++pci_map_page(struct pci_dev *hwdev, struct page *page,
++ unsigned long offset, size_t size, int direction)
++{
++ return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
++ size_t size, int direction)
++{
++ dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
++}
++
++static inline int
++pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
++}
++
++static inline int
++pci_dma_mapping_error(dma_addr_t dma_addr)
++{
++ return dma_mapping_error(dma_addr);
++}
++
++#endif
+--- linux/include/asm-generic/pci.h
++++ linux/include/asm-generic/pci.h
+@@ -0,0 +1,34 @@
++/*
++ * linux/include/asm-generic/pci.h
++ *
++ * Copyright (C) 2003 Russell King
++ */
++#ifndef _ASM_GENERIC_PCI_H
++#define _ASM_GENERIC_PCI_H
++
++/**
++ * pcibios_resource_to_bus - convert resource to PCI bus address
++ * @dev: device which owns this resource
++ * @region: converted bus-centric region (start,end)
++ * @res: resource to convert
++ *
++ * Convert a resource to a PCI device bus address or bus window.
++ */
++static inline void
++pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
++ struct resource *res)
++{
++ region->start = res->start;
++ region->end = res->end;
++}
++
++#define pcibios_scan_all_fns(a, b) 0
++
++#ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
++static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
++{
++ return channel ? 15 : 14;
++}
++#endif /* HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ */
++
++#endif
+--- linux/include/asm-generic/percpu.h
++++ linux/include/asm-generic/percpu.h
+@@ -0,0 +1,42 @@
++#ifndef _ASM_GENERIC_PERCPU_H_
++#define _ASM_GENERIC_PERCPU_H_
++#include <linux/compiler.h>
++
++#define __GENERIC_PER_CPU
++#ifdef CONFIG_SMP
++
++extern unsigned long __per_cpu_offset[NR_CPUS];
++
++/* Separate out the type, so (int[3], foo) works. */
++#define DEFINE_PER_CPU(type, name) \
++ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
++
++/* var is in discarded region: offset to particular copy we want */
++#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
++#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
++
++/* A macro to avoid #include hell... */
++#define percpu_modcopy(pcpudst, src, size) \
++do { \
++ unsigned int __i; \
++ for (__i = 0; __i < NR_CPUS; __i++) \
++ if (cpu_possible(__i)) \
++ memcpy((pcpudst)+__per_cpu_offset[__i], \
++ (src), (size)); \
++} while (0)
++#else /* ! SMP */
++
++#define DEFINE_PER_CPU(type, name) \
++ __typeof__(type) per_cpu__##name
++
++#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
++#define __get_cpu_var(var) per_cpu__##var
++
++#endif /* SMP */
++
++#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
++
++#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
++#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
++
++#endif /* _ASM_GENERIC_PERCPU_H_ */
+--- linux/include/asm-generic/pgtable.h
++++ linux/include/asm-generic/pgtable.h
+@@ -0,0 +1,137 @@
++#ifndef _ASM_GENERIC_PGTABLE_H
++#define _ASM_GENERIC_PGTABLE_H
++
++#ifndef __HAVE_ARCH_PTEP_ESTABLISH
++/*
++ * Establish a new mapping:
++ * - flush the old one
++ * - update the page tables
++ * - inform the TLB about the new one
++ *
++ * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock.
++ *
++ * Note: the old pte is known to not be writable, so we don't need to
++ * worry about dirty bits etc getting lost.
++ */
++#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
++#define ptep_establish(__vma, __address, __ptep, __entry) \
++do { \
++ set_pte(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
++#define ptep_establish(__vma, __address, __ptep, __entry) \
++do { \
++ set_pte_atomic(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++/*
++ * Largely same as above, but only sets the access flags (dirty,
++ * accessed, and writable). Furthermore, we know it always gets set
++ * to a "more permissive" setting, which allows most architectures
++ * to optimize this.
++ */
++#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
++do { \
++ set_pte(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++static inline int ptep_test_and_clear_young(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ if (!pte_young(pte))
++ return 0;
++ set_pte(ptep, pte_mkold(pte));
++ return 1;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define ptep_clear_flush_young(__vma, __address, __ptep) \
++({ \
++ int __young = ptep_test_and_clear_young(__ptep); \
++ if (__young) \
++ flush_tlb_page(__vma, __address); \
++ __young; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++static inline int ptep_test_and_clear_dirty(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ if (!pte_dirty(pte))
++ return 0;
++ set_pte(ptep, pte_mkclean(pte));
++ return 1;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
++#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
++({ \
++ int __dirty = ptep_test_and_clear_dirty(__ptep); \
++ if (__dirty) \
++ flush_tlb_page(__vma, __address); \
++ __dirty; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
++static inline pte_t ptep_get_and_clear(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ pte_clear(ptep);
++ return pte;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
++#define ptep_clear_flush(__vma, __address, __ptep) \
++({ \
++ pte_t __pte = ptep_get_and_clear(__ptep); \
++ flush_tlb_page(__vma, __address); \
++ __pte; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
++static inline void ptep_set_wrprotect(pte_t *ptep)
++{
++ pte_t old_pte = *ptep;
++ set_pte(ptep, pte_wrprotect(old_pte));
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_MKDIRTY
++static inline void ptep_mkdirty(pte_t *ptep)
++{
++ pte_t old_pte = *ptep;
++ set_pte(ptep, pte_mkdirty(old_pte));
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTE_SAME
++#define pte_same(A,B) (pte_val(A) == pte_val(B))
++#endif
++
++#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
++#define page_test_and_clear_dirty(page) (0)
++#endif
++
++#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
++#define page_test_and_clear_young(page) (0)
++#endif
++
++#ifndef __HAVE_ARCH_PGD_OFFSET_GATE
++#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr)
++#endif
++
++#endif /* _ASM_GENERIC_PGTABLE_H */
+--- linux/include/asm-generic/pgtable-nopmd.h
++++ linux/include/asm-generic/pgtable-nopmd.h
+@@ -0,0 +1,60 @@
++#ifndef _PGTABLE_NOPMD_H
++#define _PGTABLE_NOPMD_H
++
++#ifndef __ASSEMBLY__
++
++#include <asm-generic/pgtable-nopud.h>
++
++/*
++ * Having the pmd type consist of a pud gets the size right, and allows
++ * us to conceptually access the pud entry that this pmd is folded into
++ * without casting.
++ */
++typedef struct { pud_t pud; } pmd_t;
++
++#define PMD_SHIFT PUD_SHIFT
++#define PTRS_PER_PMD 1
++#define PMD_SIZE (1UL << PMD_SHIFT)
++#define PMD_MASK (~(PMD_SIZE-1))
++
++/*
++ * The "pud_xxx()" functions here are trivial for a folded two-level
++ * setup: the pmd is never bad, and a pmd always exists (as it's folded
++ * into the pud entry)
++ */
++static inline int pud_none(pud_t pud) { return 0; }
++static inline int pud_bad(pud_t pud) { return 0; }
++static inline int pud_present(pud_t pud) { return 1; }
++static inline void pud_clear(pud_t *pud) { }
++#define pmd_ERROR(pmd) (pud_ERROR((pmd).pud))
++
++#define pud_populate(mm, pmd, pte) do { } while (0)
++
++/*
++ * (pmds are folded into puds so this doesn't get actually called,
++ * but the define is needed for a generic inline function.)
++ */
++#define set_pud(pudptr, pudval) set_pmd((pmd_t *)(pudptr), (pmd_t) { pudval })
++
++static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
++{
++ return (pmd_t *)pud;
++}
++
++#define pmd_val(x) (pud_val((x).pud))
++#define __pmd(x) ((pmd_t) { __pud(x) } )
++
++#define pud_page(pud) (pmd_page((pmd_t){ pud }))
++#define pud_page_kernel(pud) (pmd_page_kernel((pmd_t){ pud }))
++
++/*
++ * allocating and freeing a pmd is trivial: the 1-entry pmd is
++ * inside the pud, so has no extra memory associated with it.
++ */
++#define pmd_alloc_one(mm, address) NULL
++#define pmd_free(x) do { } while (0)
++#define __pmd_free_tlb(tlb, x) do { } while (0)
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _PGTABLE_NOPMD_H */
+--- linux/include/asm-generic/pgtable-nopud.h
++++ linux/include/asm-generic/pgtable-nopud.h
+@@ -0,0 +1,56 @@
++#ifndef _PGTABLE_NOPUD_H
++#define _PGTABLE_NOPUD_H
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Having the pud type consist of a pgd gets the size right, and allows
++ * us to conceptually access the pgd entry that this pud is folded into
++ * without casting.
++ */
++typedef struct { pgd_t pgd; } pud_t;
++
++#define PUD_SHIFT PGDIR_SHIFT
++#define PTRS_PER_PUD 1
++#define PUD_SIZE (1UL << PUD_SHIFT)
++#define PUD_MASK (~(PUD_SIZE-1))
++
++/*
++ * The "pgd_xxx()" functions here are trivial for a folded two-level
++ * setup: the pud is never bad, and a pud always exists (as it's folded
++ * into the pgd entry)
++ */
++static inline int pgd_none(pgd_t pgd) { return 0; }
++static inline int pgd_bad(pgd_t pgd) { return 0; }
++static inline int pgd_present(pgd_t pgd) { return 1; }
++static inline void pgd_clear(pgd_t *pgd) { }
++#define pud_ERROR(pud) (pgd_ERROR((pud).pgd))
++
++#define pgd_populate(mm, pgd, pud) do { } while (0)
++/*
++ * (puds are folded into pgds so this doesn't get actually called,
++ * but the define is needed for a generic inline function.)
++ */
++#define set_pgd(pgdptr, pgdval) set_pud((pud_t *)(pgdptr), (pud_t) { pgdval })
++
++static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
++{
++ return (pud_t *)pgd;
++}
++
++#define pud_val(x) (pgd_val((x).pgd))
++#define __pud(x) ((pud_t) { __pgd(x) } )
++
++#define pgd_page(pgd) (pud_page((pud_t){ pgd }))
++#define pgd_page_kernel(pgd) (pud_page_kernel((pud_t){ pgd }))
++
++/*
++ * allocating and freeing a pud is trivial: the 1-entry pud is
++ * inside the pgd, so has no extra memory associated with it.
++ */
++#define pud_alloc_one(mm, address) NULL
++#define pud_free(x) do { } while (0)
++#define __pud_free_tlb(tlb, x) do { } while (0)
++
++#endif /* __ASSEMBLY__ */
++#endif /* _PGTABLE_NOPUD_H */
+--- linux/include/asm-generic/resource.h
++++ linux/include/asm-generic/resource.h
+@@ -0,0 +1,60 @@
++#ifndef _ASM_GENERIC_RESOURCE_H
++#define _ASM_GENERIC_RESOURCE_H
++
++/*
++ * Resource limits
++ */
++
++/* Allow arch to control resource order */
++#ifndef __ARCH_RLIMIT_ORDER
++#define RLIMIT_CPU 0 /* CPU time in ms */
++#define RLIMIT_FSIZE 1 /* Maximum filesize */
++#define RLIMIT_DATA 2 /* max data size */
++#define RLIMIT_STACK 3 /* max stack size */
++#define RLIMIT_CORE 4 /* max core file size */
++#define RLIMIT_RSS 5 /* max resident set size */
++#define RLIMIT_NPROC 6 /* max number of processes */
++#define RLIMIT_NOFILE 7 /* max number of open files */
++#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
++#define RLIMIT_AS 9 /* address space limit */
++#define RLIMIT_LOCKS 10 /* maximum file locks held */
++#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
++#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
++
++#define RLIM_NLIMITS 13
++#endif
++
++/*
++ * SuS says limits have to be unsigned.
++ * Which makes a ton more sense anyway.
++ */
++#ifndef RLIM_INFINITY
++#define RLIM_INFINITY (~0UL)
++#endif
++
++#ifndef _STK_LIM_MAX
++#define _STK_LIM_MAX RLIM_INFINITY
++#endif
++
++#ifdef __KERNEL__
++
++#define INIT_RLIMITS \
++{ \
++ [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
++ [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
++ [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_NPROC] = { 0, 0 }, \
++ [RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
++ [RLIMIT_MEMLOCK] = { MLOCK_LIMIT, MLOCK_LIMIT }, \
++ [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
++ [RLIMIT_SIGPENDING] = { MAX_SIGPENDING, MAX_SIGPENDING }, \
++ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
++}
++
++#endif /* __KERNEL__ */
++
++#endif
+--- linux/include/asm-generic/rmap.h
++++ linux/include/asm-generic/rmap.h
+@@ -0,0 +1,90 @@
++#ifndef _GENERIC_RMAP_H
++#define _GENERIC_RMAP_H
++/*
++ * linux/include/asm-generic/rmap.h
++ *
++ * Architecture dependent parts of the reverse mapping code,
++ * this version should work for most architectures with a
++ * 'normal' page table layout.
++ *
++ * We use the struct page of the page table page to find out
++ * the process and full address of a page table entry:
++ * - page->mapping points to the process' mm_struct
++ * - page->index has the high bits of the address
++ * - the lower bits of the address are calculated from the
++ * offset of the page table entry within the page table page
++ *
++ * For CONFIG_HIGHPTE, we need to represent the address of a pte in a
++ * scalar pte_addr_t. The pfn of the pte's page is shifted left by PAGE_SIZE
++ * bits and is then ORed with the byte offset of the pte within its page.
++ *
++ * For CONFIG_HIGHMEM4G, the pte_addr_t is 32 bits. 20 for the pfn, 12 for
++ * the offset.
++ *
++ * For CONFIG_HIGHMEM64G, the pte_addr_t is 64 bits. 52 for the pfn, 12 for
++ * the offset.
++ */
++#include <linux/mm.h>
++
++static inline void pgtable_add_rmap(struct page * page, struct mm_struct * mm, unsigned long address)
++{
++#ifdef BROKEN_PPC_PTE_ALLOC_ONE
++ /* OK, so PPC calls pte_alloc() before mem_map[] is setup ... ;( */
++ extern int mem_init_done;
++
++ if (!mem_init_done)
++ return;
++#endif
++ page->mapping = (void *)mm;
++ page->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1);
++ inc_page_state(nr_page_table_pages);
++}
++
++static inline void pgtable_remove_rmap(struct page * page)
++{
++ page->mapping = NULL;
++ page->index = 0;
++ dec_page_state(nr_page_table_pages);
++}
++
++static inline struct mm_struct * ptep_to_mm(pte_t * ptep)
++{
++ struct page * page = kmap_atomic_to_page(ptep);
++ return (struct mm_struct *) page->mapping;
++}
++
++static inline unsigned long ptep_to_address(pte_t * ptep)
++{
++ struct page * page = kmap_atomic_to_page(ptep);
++ unsigned long low_bits;
++ low_bits = ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
++ return page->index + low_bits;
++}
++
++#ifdef CONFIG_HIGHPTE
++static inline pte_addr_t ptep_to_paddr(pte_t *ptep)
++{
++ pte_addr_t paddr;
++ paddr = ((pte_addr_t)page_to_pfn(kmap_atomic_to_page(ptep))) << PAGE_SHIFT;
++ return paddr + (pte_addr_t)((unsigned long)ptep & ~PAGE_MASK);
++}
++#else
++static inline pte_addr_t ptep_to_paddr(pte_t *ptep)
++{
++ return (pte_addr_t)ptep;
++}
++#endif
++
++#ifndef CONFIG_HIGHPTE
++static inline pte_t *rmap_ptep_map(pte_addr_t pte_paddr)
++{
++ return (pte_t *)pte_paddr;
++}
++
++static inline void rmap_ptep_unmap(pte_t *pte)
++{
++ return;
++}
++#endif
++
++#endif /* _GENERIC_RMAP_H */
+--- linux/include/asm-generic/rtc.h
++++ linux/include/asm-generic/rtc.h
+@@ -0,0 +1,213 @@
++/*
++ * inclue/asm-generic/rtc.h
++ *
++ * Author: Tom Rini <trini@mvista.com>
++ *
++ * Based on:
++ * drivers/char/rtc.c
++ *
++ * Please read the COPYING file for all license details.
++ */
++
++#ifndef __ASM_RTC_H__
++#define __ASM_RTC_H__
++
++#ifdef __KERNEL__
++
++#include <linux/mc146818rtc.h>
++#include <linux/rtc.h>
++#include <linux/bcd.h>
++
++#define RTC_PIE 0x40 /* periodic interrupt enable */
++#define RTC_AIE 0x20 /* alarm interrupt enable */
++#define RTC_UIE 0x10 /* update-finished interrupt enable */
++
++/* some dummy definitions */
++#define RTC_BATT_BAD 0x100 /* battery bad */
++#define RTC_SQWE 0x08 /* enable square-wave output */
++#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
++#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
++#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
++
++/*
++ * Returns true if a clock update is in progress
++ */
++static inline unsigned char rtc_is_updating(void)
++{
++ unsigned char uip;
++
++ spin_lock_irq(&rtc_lock);
++ uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
++ spin_unlock_irq(&rtc_lock);
++ return uip;
++}
++
++static inline unsigned int get_rtc_time(struct rtc_time *time)
++{
++ unsigned long uip_watchdog = jiffies;
++ unsigned char ctrl;
++#ifdef CONFIG_MACH_DECSTATION
++ unsigned int real_year;
++#endif
++
++ /*
++ * read RTC once any update in progress is done. The update
++ * can take just over 2ms. We wait 10 to 20ms. There is no need to
++ * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
++ * If you need to know *exactly* when a second has started, enable
++ * periodic update complete interrupts, (via ioctl) and then
++ * immediately read /dev/rtc which will block until you get the IRQ.
++ * Once the read clears, read the RTC time (again via ioctl). Easy.
++ */
++
++ if (rtc_is_updating() != 0)
++ while (jiffies - uip_watchdog < 2*HZ/100) {
++ barrier();
++ cpu_relax();
++ }
++
++ /*
++ * Only the values that we read from the RTC are set. We leave
++ * tm_wday, tm_yday and tm_isdst untouched. Even though the
++ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
++ * by the RTC when initially set to a non-zero value.
++ */
++ spin_lock_irq(&rtc_lock);
++ time->tm_sec = CMOS_READ(RTC_SECONDS);
++ time->tm_min = CMOS_READ(RTC_MINUTES);
++ time->tm_hour = CMOS_READ(RTC_HOURS);
++ time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
++ time->tm_mon = CMOS_READ(RTC_MONTH);
++ time->tm_year = CMOS_READ(RTC_YEAR);
++#ifdef CONFIG_MACH_DECSTATION
++ real_year = CMOS_READ(RTC_DEC_YEAR);
++#endif
++ ctrl = CMOS_READ(RTC_CONTROL);
++ spin_unlock_irq(&rtc_lock);
++
++ if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
++ {
++ BCD_TO_BIN(time->tm_sec);
++ BCD_TO_BIN(time->tm_min);
++ BCD_TO_BIN(time->tm_hour);
++ BCD_TO_BIN(time->tm_mday);
++ BCD_TO_BIN(time->tm_mon);
++ BCD_TO_BIN(time->tm_year);
++ }
++
++#ifdef CONFIG_MACH_DECSTATION
++ time->tm_year += real_year - 72;
++#endif
++
++ /*
++ * Account for differences between how the RTC uses the values
++ * and how they are defined in a struct rtc_time;
++ */
++ if (time->tm_year <= 69)
++ time->tm_year += 100;
++
++ time->tm_mon--;
++
++ return RTC_24H;
++}
++
++/* Set the current date and time in the real time clock. */
++static inline int set_rtc_time(struct rtc_time *time)
++{
++ unsigned char mon, day, hrs, min, sec;
++ unsigned char save_control, save_freq_select;
++ unsigned int yrs;
++#ifdef CONFIG_MACH_DECSTATION
++ unsigned int real_yrs, leap_yr;
++#endif
++
++ yrs = time->tm_year;
++ mon = time->tm_mon + 1; /* tm_mon starts at zero */
++ day = time->tm_mday;
++ hrs = time->tm_hour;
++ min = time->tm_min;
++ sec = time->tm_sec;
++
++ if (yrs > 255) /* They are unsigned */
++ return -EINVAL;
++
++ spin_lock_irq(&rtc_lock);
++#ifdef CONFIG_MACH_DECSTATION
++ real_yrs = yrs;
++ leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
++ !((yrs + 1900) % 400));
++ yrs = 72;
++
++ /*
++ * We want to keep the year set to 73 until March
++ * for non-leap years, so that Feb, 29th is handled
++ * correctly.
++ */
++ if (!leap_yr && mon < 3) {
++ real_yrs--;
++ yrs = 73;
++ }
++#endif
++ /* These limits and adjustments are independent of
++ * whether the chip is in binary mode or not.
++ */
++ if (yrs > 169) {
++ spin_unlock_irq(&rtc_lock);
++ return -EINVAL;
++ }
++
++ if (yrs >= 100)
++ yrs -= 100;
++
++ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
++ || RTC_ALWAYS_BCD) {
++ BIN_TO_BCD(sec);
++ BIN_TO_BCD(min);
++ BIN_TO_BCD(hrs);
++ BIN_TO_BCD(day);
++ BIN_TO_BCD(mon);
++ BIN_TO_BCD(yrs);
++ }
++
++ save_control = CMOS_READ(RTC_CONTROL);
++ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
++ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
++ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
++
++#ifdef CONFIG_MACH_DECSTATION
++ CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
++#endif
++ CMOS_WRITE(yrs, RTC_YEAR);
++ CMOS_WRITE(mon, RTC_MONTH);
++ CMOS_WRITE(day, RTC_DAY_OF_MONTH);
++ CMOS_WRITE(hrs, RTC_HOURS);
++ CMOS_WRITE(min, RTC_MINUTES);
++ CMOS_WRITE(sec, RTC_SECONDS);
++
++ CMOS_WRITE(save_control, RTC_CONTROL);
++ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
++
++ spin_unlock_irq(&rtc_lock);
++
++ return 0;
++}
++
++static inline unsigned int get_rtc_ss(void)
++{
++ struct rtc_time h;
++
++ get_rtc_time(&h);
++ return h.tm_sec;
++}
++
++static inline int get_rtc_pll(struct rtc_pll_info *pll)
++{
++ return -EINVAL;
++}
++static inline int set_rtc_pll(struct rtc_pll_info *pll)
++{
++ return -EINVAL;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __ASM_RTC_H__ */
+--- linux/include/asm-generic/sections.h
++++ linux/include/asm-generic/sections.h
+@@ -0,0 +1,13 @@
++#ifndef _ASM_GENERIC_SECTIONS_H_
++#define _ASM_GENERIC_SECTIONS_H_
++
++/* References to section boundaries */
++
++extern char _text[], _stext[], _etext[];
++extern char _data[], _sdata[], _edata[];
++extern char __bss_start[], __bss_stop[];
++extern char __init_begin[], __init_end[];
++extern char _sinittext[], _einittext[];
++extern char _end[];
++
++#endif /* _ASM_GENERIC_SECTIONS_H_ */
+--- linux/include/asm-generic/siginfo.h
++++ linux/include/asm-generic/siginfo.h
+@@ -0,0 +1,288 @@
++#ifndef _ASM_GENERIC_SIGINFO_H
++#define _ASM_GENERIC_SIGINFO_H
++
++#include <linux/compiler.h>
++#include <linux/types.h>
++#include <linux/resource.h>
++
++typedef union sigval {
++ int sival_int;
++ void __user *sival_ptr;
++} sigval_t;
++
++/*
++ * This is the size (including padding) of the part of the
++ * struct siginfo that is before the union.
++ */
++#ifndef __ARCH_SI_PREAMBLE_SIZE
++#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
++#endif
++
++#define SI_MAX_SIZE 128
++#ifndef SI_PAD_SIZE
++#define SI_PAD_SIZE ((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
++#endif
++
++#ifndef __ARCH_SI_UID_T
++#define __ARCH_SI_UID_T uid_t
++#endif
++
++/*
++ * The default "si_band" type is "long", as specified by POSIX.
++ * However, some architectures want to override this to "int"
++ * for historical compatibility reasons, so we allow that.
++ */
++#ifndef __ARCH_SI_BAND_T
++#define __ARCH_SI_BAND_T long
++#endif
++
++#ifndef HAVE_ARCH_SIGINFO_T
++
++typedef struct siginfo {
++ int si_signo;
++ int si_errno;
++ int si_code;
++
++ union {
++ int _pad[SI_PAD_SIZE];
++
++ /* kill() */
++ struct {
++ pid_t _pid; /* sender's pid */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ } _kill;
++
++ /* POSIX.1b timers */
++ struct {
++ timer_t _tid; /* timer id */
++ int _overrun; /* overrun count */
++ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
++ sigval_t _sigval; /* same as below */
++ int _sys_private; /* not to be passed to user */
++ } _timer;
++
++ /* POSIX.1b signals */
++ struct {
++ pid_t _pid; /* sender's pid */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ sigval_t _sigval;
++ } _rt;
++
++ /* SIGCHLD */
++ struct {
++ pid_t _pid; /* which child */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ int _status; /* exit code */
++ clock_t _utime;
++ clock_t _stime;
++ } _sigchld;
++
++ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
++ struct {
++ void __user *_addr; /* faulting insn/memory ref. */
++#ifdef __ARCH_SI_TRAPNO
++ int _trapno; /* TRAP # which caused the signal */
++#endif
++ } _sigfault;
++
++ /* SIGPOLL */
++ struct {
++ __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
++ int _fd;
++ } _sigpoll;
++ } _sifields;
++} siginfo_t;
++
++#endif
++
++/*
++ * How these fields are to be accessed.
++ */
++#define si_pid _sifields._kill._pid
++#define si_uid _sifields._kill._uid
++#define si_tid _sifields._timer._tid
++#define si_overrun _sifields._timer._overrun
++#define si_sys_private _sifields._timer._sys_private
++#define si_status _sifields._sigchld._status
++#define si_utime _sifields._sigchld._utime
++#define si_stime _sifields._sigchld._stime
++#define si_value _sifields._rt._sigval
++#define si_int _sifields._rt._sigval.sival_int
++#define si_ptr _sifields._rt._sigval.sival_ptr
++#define si_addr _sifields._sigfault._addr
++#ifdef __ARCH_SI_TRAPNO
++#define si_trapno _sifields._sigfault._trapno
++#endif
++#define si_band _sifields._sigpoll._band
++#define si_fd _sifields._sigpoll._fd
++
++#ifdef __KERNEL__
++#define __SI_MASK 0xffff0000u
++#define __SI_KILL (0 << 16)
++#define __SI_TIMER (1 << 16)
++#define __SI_POLL (2 << 16)
++#define __SI_FAULT (3 << 16)
++#define __SI_CHLD (4 << 16)
++#define __SI_RT (5 << 16)
++#define __SI_MESGQ (6 << 16)
++#define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
++#else
++#define __SI_KILL 0
++#define __SI_TIMER 0
++#define __SI_POLL 0
++#define __SI_FAULT 0
++#define __SI_CHLD 0
++#define __SI_RT 0
++#define __SI_MESGQ 0
++#define __SI_CODE(T,N) (N)
++#endif
++
++/*
++ * si_code values
++ * Digital reserves positive values for kernel-generated signals.
++ */
++#define SI_USER 0 /* sent by kill, sigsend, raise */
++#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
++#define SI_QUEUE -1 /* sent by sigqueue */
++#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
++#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change */
++#define SI_ASYNCIO -4 /* sent by AIO completion */
++#define SI_SIGIO -5 /* sent by queued SIGIO */
++#define SI_TKILL -6 /* sent by tkill system call */
++#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
++
++#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
++#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
++
++/*
++ * SIGILL si_codes
++ */
++#define ILL_ILLOPC (__SI_FAULT|1) /* illegal opcode */
++#define ILL_ILLOPN (__SI_FAULT|2) /* illegal operand */
++#define ILL_ILLADR (__SI_FAULT|3) /* illegal addressing mode */
++#define ILL_ILLTRP (__SI_FAULT|4) /* illegal trap */
++#define ILL_PRVOPC (__SI_FAULT|5) /* privileged opcode */
++#define ILL_PRVREG (__SI_FAULT|6) /* privileged register */
++#define ILL_COPROC (__SI_FAULT|7) /* coprocessor error */
++#define ILL_BADSTK (__SI_FAULT|8) /* internal stack error */
++#define NSIGILL 8
++
++/*
++ * SIGFPE si_codes
++ */
++#define FPE_INTDIV (__SI_FAULT|1) /* integer divide by zero */
++#define FPE_INTOVF (__SI_FAULT|2) /* integer overflow */
++#define FPE_FLTDIV (__SI_FAULT|3) /* floating point divide by zero */
++#define FPE_FLTOVF (__SI_FAULT|4) /* floating point overflow */
++#define FPE_FLTUND (__SI_FAULT|5) /* floating point underflow */
++#define FPE_FLTRES (__SI_FAULT|6) /* floating point inexact result */
++#define FPE_FLTINV (__SI_FAULT|7) /* floating point invalid operation */
++#define FPE_FLTSUB (__SI_FAULT|8) /* subscript out of range */
++#define NSIGFPE 8
++
++/*
++ * SIGSEGV si_codes
++ */
++#define SEGV_MAPERR (__SI_FAULT|1) /* address not mapped to object */
++#define SEGV_ACCERR (__SI_FAULT|2) /* invalid permissions for mapped object */
++#define NSIGSEGV 2
++
++/*
++ * SIGBUS si_codes
++ */
++#define BUS_ADRALN (__SI_FAULT|1) /* invalid address alignment */
++#define BUS_ADRERR (__SI_FAULT|2) /* non-existant physical address */
++#define BUS_OBJERR (__SI_FAULT|3) /* object specific hardware error */
++#define NSIGBUS 3
++
++/*
++ * SIGTRAP si_codes
++ */
++#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */
++#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
++#define NSIGTRAP 2
++
++/*
++ * SIGCHLD si_codes
++ */
++#define CLD_EXITED (__SI_CHLD|1) /* child has exited */
++#define CLD_KILLED (__SI_CHLD|2) /* child was killed */
++#define CLD_DUMPED (__SI_CHLD|3) /* child terminated abnormally */
++#define CLD_TRAPPED (__SI_CHLD|4) /* traced child has trapped */
++#define CLD_STOPPED (__SI_CHLD|5) /* child has stopped */
++#define CLD_CONTINUED (__SI_CHLD|6) /* stopped child has continued */
++#define NSIGCHLD 6
++
++/*
++ * SIGPOLL si_codes
++ */
++#define POLL_IN (__SI_POLL|1) /* data input available */
++#define POLL_OUT (__SI_POLL|2) /* output buffers available */
++#define POLL_MSG (__SI_POLL|3) /* input message available */
++#define POLL_ERR (__SI_POLL|4) /* i/o error */
++#define POLL_PRI (__SI_POLL|5) /* high priority input available */
++#define POLL_HUP (__SI_POLL|6) /* device disconnected */
++#define NSIGPOLL 6
++
++/*
++ * sigevent definitions
++ *
++ * It seems likely that SIGEV_THREAD will have to be handled from
++ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
++ * thread manager then catches and does the appropriate nonsense.
++ * However, everything is written out here so as to not get lost.
++ */
++#define SIGEV_SIGNAL 0 /* notify via signal */
++#define SIGEV_NONE 1 /* other notification: meaningless */
++#define SIGEV_THREAD 2 /* deliver via thread creation */
++#define SIGEV_THREAD_ID 4 /* deliver to thread */
++
++#define SIGEV_MAX_SIZE 64
++#ifndef SIGEV_PAD_SIZE
++#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
++#endif
++
++typedef struct sigevent {
++ sigval_t sigev_value;
++ int sigev_signo;
++ int sigev_notify;
++ union {
++ int _pad[SIGEV_PAD_SIZE];
++ int _tid;
++
++ struct {
++ void (*_function)(sigval_t);
++ void *_attribute; /* really pthread_attr_t */
++ } _sigev_thread;
++ } _sigev_un;
++} sigevent_t;
++
++#define sigev_notify_function _sigev_un._sigev_thread._function
++#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
++#define sigev_notify_thread_id _sigev_un._tid
++
++#ifdef __KERNEL__
++
++struct siginfo;
++void do_schedule_next_timer(struct siginfo *info);
++
++#ifndef HAVE_ARCH_COPY_SIGINFO
++
++#include <linux/string.h>
++
++static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
++{
++ if (from->si_code < 0)
++ memcpy(to, from, sizeof(*to));
++ else
++ /* _sigchld is currently the largest know union member */
++ memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
++}
++
++#endif
++
++extern int copy_siginfo_to_user(struct siginfo __user *to, struct siginfo *from);
++
++#endif /* __KERNEL__ */
++
++#endif
+--- linux/include/asm-generic/statfs.h
++++ linux/include/asm-generic/statfs.h
+@@ -0,0 +1,51 @@
++#ifndef _GENERIC_STATFS_H
++#define _GENERIC_STATFS_H
++
++#ifndef __KERNEL_STRICT_NAMES
++# include <linux/types.h>
++typedef __kernel_fsid_t fsid_t;
++#endif
++
++struct statfs {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u32 f_blocks;
++ __u32 f_bfree;
++ __u32 f_bavail;
++ __u32 f_files;
++ __u32 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++struct statfs64 {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u64 f_blocks;
++ __u64 f_bfree;
++ __u64 f_bavail;
++ __u64 f_files;
++ __u64 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++struct compat_statfs64 {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u64 f_blocks;
++ __u64 f_bfree;
++ __u64 f_bavail;
++ __u64 f_files;
++ __u64 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++#endif
+--- linux/include/asm-generic/termios.h
++++ linux/include/asm-generic/termios.h
+@@ -0,0 +1,69 @@
++/* termios.h: generic termios/termio user copying/translation
++ */
++
++#ifndef _ASM_GENERIC_TERMIOS_H
++#define _ASM_GENERIC_TERMIOS_H
++
++#include <asm/uaccess.h>
++
++#ifndef __ARCH_TERMIO_GETPUT
++
++/*
++ * Translate a "termio" structure into a "termios". Ugh.
++ */
++static inline int user_termio_to_kernel_termios(struct termios *termios,
++ struct termio __user *termio)
++{
++ unsigned short tmp;
++
++ if (get_user(tmp, &termio->c_iflag) < 0)
++ goto fault;
++ termios->c_iflag = (0xffff0000 & termios->c_iflag) | tmp;
++
++ if (get_user(tmp, &termio->c_oflag) < 0)
++ goto fault;
++ termios->c_oflag = (0xffff0000 & termios->c_oflag) | tmp;
++
++ if (get_user(tmp, &termio->c_cflag) < 0)
++ goto fault;
++ termios->c_cflag = (0xffff0000 & termios->c_cflag) | tmp;
++
++ if (get_user(tmp, &termio->c_lflag) < 0)
++ goto fault;
++ termios->c_lflag = (0xffff0000 & termios->c_lflag) | tmp;
++
++ if (get_user(termios->c_line, &termio->c_line) < 0)
++ goto fault;
++
++ if (copy_from_user(termios->c_cc, termio->c_cc, NCC) != 0)
++ goto fault;
++
++ return 0;
++
++ fault:
++ return -EFAULT;
++}
++
++/*
++ * Translate a "termios" structure into a "termio". Ugh.
++ */
++static inline int kernel_termios_to_user_termio(struct termio __user *termio,
++ struct termios *termios)
++{
++ if (put_user(termios->c_iflag, &termio->c_iflag) < 0 ||
++ put_user(termios->c_oflag, &termio->c_oflag) < 0 ||
++ put_user(termios->c_cflag, &termio->c_cflag) < 0 ||
++ put_user(termios->c_lflag, &termio->c_lflag) < 0 ||
++ put_user(termios->c_line, &termio->c_line) < 0 ||
++ copy_to_user(termio->c_cc, termios->c_cc, NCC) != 0)
++ return -EFAULT;
++
++ return 0;
++}
++
++#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#endif /* __ARCH_TERMIO_GETPUT */
++
++#endif /* _ASM_GENERIC_TERMIOS_H */
+--- linux/include/asm-generic/tlb.h
++++ linux/include/asm-generic/tlb.h
+@@ -0,0 +1,160 @@
++/* asm-generic/tlb.h
++ *
++ * Generic TLB shootdown code
++ *
++ * Copyright 2001 Red Hat, Inc.
++ * Based on code from mm/memory.c Copyright Linus Torvalds and others.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#ifndef _ASM_GENERIC__TLB_H
++#define _ASM_GENERIC__TLB_H
++
++// #include <linux/config.h>
++#include <linux/swap.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++
++/*
++ * For UP we don't need to worry about TLB flush
++ * and page free order so much..
++ */
++#ifdef CONFIG_SMP
++ #define FREE_PTE_NR 506
++ #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
++#else
++ #define FREE_PTE_NR 1
++ #define tlb_fast_mode(tlb) 1
++#endif
++
++/* struct mmu_gather is an opaque type used by the mm code for passing around
++ * any data needed by arch specific code for tlb_remove_page. This structure
++ * can be per-CPU or per-MM as the page table lock is held for the duration of
++ * TLB shootdown.
++ */
++struct mmu_gather {
++ struct mm_struct *mm;
++ unsigned int nr; /* set to ~0U means fast mode */
++ unsigned int need_flush;/* Really unmapped some ptes? */
++ unsigned int fullmm; /* non-zero means full mm flush */
++ unsigned long freed;
++ struct page * pages[FREE_PTE_NR];
++};
++
++/* Users of the generic TLB shootdown code must declare this storage space. */
++DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++/* tlb_gather_mmu
++ * Return a pointer to an initialized struct mmu_gather.
++ */
++static inline struct mmu_gather *
++tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
++{
++ struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id());
++
++ tlb->mm = mm;
++
++ /* Use fast mode if only one CPU is online */
++ tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
++
++ tlb->fullmm = full_mm_flush;
++ tlb->freed = 0;
++
++ return tlb;
++}
++
++static inline void
++tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++ if (!tlb->need_flush)
++ return;
++ tlb->need_flush = 0;
++ tlb_flush(tlb);
++ if (!tlb_fast_mode(tlb)) {
++ free_pages_and_swap_cache(tlb->pages, tlb->nr);
++ tlb->nr = 0;
++ }
++}
++
++/* tlb_finish_mmu
++ * Called at the end of the shootdown operation to free up any resources
++ * that were required. The page table lock is still held at this point.
++ */
++static inline void
++tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++ int freed = tlb->freed;
++ struct mm_struct *mm = tlb->mm;
++ int rss = mm->rss;
++
++ if (rss < freed)
++ freed = rss;
++ mm->rss = rss - freed;
++ tlb_flush_mmu(tlb, start, end);
++
++ /* keep the page table cache within bounds */
++ check_pgt_cache();
++}
++
++static inline unsigned int
++tlb_is_full_mm(struct mmu_gather *tlb)
++{
++ return tlb->fullmm;
++}
++
++/* tlb_remove_page
++ * Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while
++ * handling the additional races in SMP caused by other CPUs caching valid
++ * mappings in their TLBs.
++ */
++static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
++{
++ tlb->need_flush = 1;
++ if (tlb_fast_mode(tlb)) {
++ free_page_and_swap_cache(page);
++ return;
++ }
++ tlb->pages[tlb->nr++] = page;
++ if (tlb->nr >= FREE_PTE_NR)
++ tlb_flush_mmu(tlb, 0, 0);
++}
++
++/**
++ * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
++ *
++ * Record the fact that pte's were really umapped in ->need_flush, so we can
++ * later optimise away the tlb invalidate. This helps when userspace is
++ * unmapping already-unmapped pages, which happens quite a lot.
++ */
++#define tlb_remove_tlb_entry(tlb, ptep, address) \
++ do { \
++ tlb->need_flush = 1; \
++ __tlb_remove_tlb_entry(tlb, ptep, address); \
++ } while (0)
++
++#define pte_free_tlb(tlb, ptep) \
++ do { \
++ tlb->need_flush = 1; \
++ __pte_free_tlb(tlb, ptep); \
++ } while (0)
++
++#ifndef __ARCH_HAS_4LEVEL_HACK
++#define pud_free_tlb(tlb, pudp) \
++ do { \
++ tlb->need_flush = 1; \
++ __pud_free_tlb(tlb, pudp); \
++ } while (0)
++#endif
++
++#define pmd_free_tlb(tlb, pmdp) \
++ do { \
++ tlb->need_flush = 1; \
++ __pmd_free_tlb(tlb, pmdp); \
++ } while (0)
++
++#define tlb_migrate_finish(mm) do {} while (0)
++
++#endif /* _ASM_GENERIC__TLB_H */
+--- linux/include/asm-generic/topology.h
++++ linux/include/asm-generic/topology.h
+@@ -0,0 +1,48 @@
++/*
++ * linux/include/asm-generic/topology.h
++ *
++ * Written by: Matthew Dobson, IBM Corporation
++ *
++ * Copyright (C) 2002, IBM Corp.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ * Send feedback to <colpatch@us.ibm.com>
++ */
++#ifndef _ASM_GENERIC_TOPOLOGY_H
++#define _ASM_GENERIC_TOPOLOGY_H
++
++/* Other architectures wishing to use this simple topology API should fill
++ in the below functions as appropriate in their own <asm/topology.h> file. */
++#ifndef cpu_to_node
++#define cpu_to_node(cpu) (0)
++#endif
++#ifndef parent_node
++#define parent_node(node) (0)
++#endif
++#ifndef node_to_cpumask
++#define node_to_cpumask(node) (cpu_online_map)
++#endif
++#ifndef node_to_first_cpu
++#define node_to_first_cpu(node) (0)
++#endif
++#ifndef pcibus_to_cpumask
++#define pcibus_to_cpumask(bus) (cpu_online_map)
++#endif
++
++#endif /* _ASM_GENERIC_TOPOLOGY_H */
+--- linux/include/asm-generic/uaccess.h
++++ linux/include/asm-generic/uaccess.h
+@@ -0,0 +1,26 @@
++#ifndef _ASM_GENERIC_UACCESS_H_
++#define _ASM_GENERIC_UACCESS_H_
++
++/*
++ * This macro should be used instead of __get_user() when accessing
++ * values at locations that are not known to be aligned.
++ */
++#define __get_user_unaligned(x, ptr) \
++({ \
++ __typeof__ (*(ptr)) __x; \
++ __copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0; \
++ (x) = __x; \
++})
++
++
++/*
++ * This macro should be used instead of __put_user() when accessing
++ * values at locations that are not known to be aligned.
++ */
++#define __put_user_unaligned(x, ptr) \
++({ \
++ __typeof__ (*(ptr)) __x = (x); \
++ __copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0; \
++})
++
++#endif /* _ASM_GENERIC_UACCESS_H */
+--- linux/include/asm-generic/unaligned.h
++++ linux/include/asm-generic/unaligned.h
+@@ -0,0 +1,20 @@
++#ifndef _ASM_GENERIC_UNALIGNED_H_
++#define _ASM_GENERIC_UNALIGNED_H_
++
++/*
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents.
++ */
++
++#include <asm/string.h>
++
++
++#define get_unaligned(ptr) \
++ ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
++
++#define put_unaligned(val, ptr) \
++ ({ __typeof__(*(ptr)) __tmp = (val); \
++ memcpy((ptr), &__tmp, sizeof(*(ptr))); \
++ (void)0; })
++
++#endif /* _ASM_GENERIC_UNALIGNED_H */
+--- linux/include/asm-generic/vmlinux.lds.h
++++ linux/include/asm-generic/vmlinux.lds.h
+@@ -0,0 +1,90 @@
++#ifndef LOAD_OFFSET
++#define LOAD_OFFSET 0
++#endif
++
++#ifndef VMLINUX_SYMBOL
++#define VMLINUX_SYMBOL(_sym_) _sym_
++#endif
++
++#define RODATA \
++ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
++ *(.rodata) *(.rodata.*) \
++ *(__vermagic) /* Kernel version magic */ \
++ } \
++ \
++ .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
++ *(.rodata1) \
++ } \
++ \
++ /* PCI quirks */ \
++ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
++ *(.pci_fixup_early) \
++ VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
++ VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
++ *(.pci_fixup_header) \
++ VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
++ VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
++ *(.pci_fixup_final) \
++ VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
++ VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
++ *(.pci_fixup_enable) \
++ VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
++ } \
++ \
++ /* Kernel symbol table: Normal symbols */ \
++ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___ksymtab) = .; \
++ *(__ksymtab) \
++ VMLINUX_SYMBOL(__stop___ksymtab) = .; \
++ } \
++ \
++ /* Kernel symbol table: GPL-only symbols */ \
++ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
++ *(__ksymtab_gpl) \
++ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
++ } \
++ \
++ /* Kernel symbol table: Normal symbols */ \
++ __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___kcrctab) = .; \
++ *(__kcrctab) \
++ VMLINUX_SYMBOL(__stop___kcrctab) = .; \
++ } \
++ \
++ /* Kernel symbol table: GPL-only symbols */ \
++ __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
++ *(__kcrctab_gpl) \
++ VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
++ } \
++ \
++ /* Kernel symbol table: strings */ \
++ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
++ *(__ksymtab_strings) \
++ } \
++ \
++ /* Built-in module parameters. */ \
++ __param : AT(ADDR(__param) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___param) = .; \
++ *(__param) \
++ VMLINUX_SYMBOL(__stop___param) = .; \
++ }
++
++#define SECURITY_INIT \
++ .security_initcall.init : { \
++ VMLINUX_SYMBOL(__security_initcall_start) = .; \
++ *(.security_initcall.init) \
++ VMLINUX_SYMBOL(__security_initcall_end) = .; \
++ }
++
++#define SCHED_TEXT \
++ VMLINUX_SYMBOL(__sched_text_start) = .; \
++ *(.sched.text) \
++ VMLINUX_SYMBOL(__sched_text_end) = .;
++
++#define LOCK_TEXT \
++ VMLINUX_SYMBOL(__lock_text_start) = .; \
++ *(.spinlock.text) \
++ VMLINUX_SYMBOL(__lock_text_end) = .;
+--- linux/include/asm-generic/xor.h
++++ linux/include/asm-generic/xor.h
+@@ -0,0 +1,718 @@
++/*
++ * include/asm-generic/xor.h
++ *
++ * Generic optimized RAID-5 checksumming functions.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * You should have received a copy of the GNU General Public License
++ * (for example /usr/src/linux/COPYING); if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <asm/processor.h>
++
++static void
++xor_8regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0];
++ p1[1] ^= p2[1];
++ p1[2] ^= p2[2];
++ p1[3] ^= p2[3];
++ p1[4] ^= p2[4];
++ p1[5] ^= p2[5];
++ p1[6] ^= p2[6];
++ p1[7] ^= p2[7];
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0];
++ p1[1] ^= p2[1] ^ p3[1];
++ p1[2] ^= p2[2] ^ p3[2];
++ p1[3] ^= p2[3] ^ p3[3];
++ p1[4] ^= p2[4] ^ p3[4];
++ p1[5] ^= p2[5] ^ p3[5];
++ p1[6] ^= p2[6] ^ p3[6];
++ p1[7] ^= p2[7] ^ p3[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0] ^ p5[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1] ^ p5[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2] ^ p5[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3] ^ p5[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4] ^ p5[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5] ^ p5[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6] ^ p5[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7] ^ p5[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ d0 ^= p5[0];
++ d1 ^= p5[1];
++ d2 ^= p5[2];
++ d3 ^= p5[3];
++ d4 ^= p5[4];
++ d5 ^= p5[5];
++ d6 ^= p5[6];
++ d7 ^= p5[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_p_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++ prefetchw(p1);
++ prefetch(p2);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ once_more:
++ p1[0] ^= p2[0];
++ p1[1] ^= p2[1];
++ p1[2] ^= p2[2];
++ p1[3] ^= p2[3];
++ p1[4] ^= p2[4];
++ p1[5] ^= p2[5];
++ p1[6] ^= p2[6];
++ p1[7] ^= p2[7];
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0];
++ p1[1] ^= p2[1] ^ p3[1];
++ p1[2] ^= p2[2] ^ p3[2];
++ p1[3] ^= p2[3] ^ p3[3];
++ p1[4] ^= p2[4] ^ p3[4];
++ p1[5] ^= p2[5] ^ p3[5];
++ p1[6] ^= p2[6] ^ p3[6];
++ p1[7] ^= p2[7] ^ p3[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++ prefetch(p5);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ prefetch(p5+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0] ^ p5[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1] ^ p5[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2] ^ p5[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3] ^ p5[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4] ^ p5[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5] ^ p5[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6] ^ p5[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7] ^ p5[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++ prefetch(p5);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ prefetch(p5+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ d0 ^= p5[0];
++ d1 ^= p5[1];
++ d2 ^= p5[2];
++ d3 ^= p5[3];
++ d4 ^= p5[4];
++ d5 ^= p5[5];
++ d6 ^= p5[6];
++ d7 ^= p5[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static struct xor_block_template xor_block_8regs = {
++ .name = "8regs",
++ .do_2 = xor_8regs_2,
++ .do_3 = xor_8regs_3,
++ .do_4 = xor_8regs_4,
++ .do_5 = xor_8regs_5,
++};
++
++static struct xor_block_template xor_block_32regs = {
++ .name = "32regs",
++ .do_2 = xor_32regs_2,
++ .do_3 = xor_32regs_3,
++ .do_4 = xor_32regs_4,
++ .do_5 = xor_32regs_5,
++};
++
++static struct xor_block_template xor_block_8regs_p = {
++ .name = "8regs_prefetch",
++ .do_2 = xor_8regs_p_2,
++ .do_3 = xor_8regs_p_3,
++ .do_4 = xor_8regs_p_4,
++ .do_5 = xor_8regs_p_5,
++};
++
++static struct xor_block_template xor_block_32regs_p = {
++ .name = "32regs_prefetch",
++ .do_2 = xor_32regs_p_2,
++ .do_3 = xor_32regs_p_3,
++ .do_4 = xor_32regs_p_4,
++ .do_5 = xor_32regs_p_5,
++};
++
++#define XOR_TRY_TEMPLATES \
++ do { \
++ xor_speed(&xor_block_8regs); \
++ xor_speed(&xor_block_8regs_p); \
++ xor_speed(&xor_block_32regs); \
++ xor_speed(&xor_block_32regs_p); \
++ } while (0)
+--- linux/include/asm-nios2nommu/altera_juart.h
++++ linux/include/asm-nios2nommu/altera_juart.h
+@@ -0,0 +1,36 @@
++/*------------------------------------------------------------------------
++ *
++ * linux/drivers/serial/altera_juart.h
++ *
++ * Driver for Altera JTAG UART core with Avalon interface
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * History:
++ * Jun/20/2005 DGT Microtronix Datacom NiosII
++ *
++ -----------------------------------------------------------------------*/
++
++#ifndef _ALTERA_JUART_H_
++ #define _ALTERA_JUART_H_
++
++ /* jtag uart details needed outside of the driver itself: */
++ /* by: arch/kernel/start.c - boot time error message(s) */
++
++ void jtaguart_console_write
++ ( struct console *co,
++ const char *s,
++ unsigned int count);
++
++#endif /* _ALTERA_JUART_H_ */
+--- linux/include/asm-nios2nommu/a.out.h
++++ linux/include/asm-nios2nommu/a.out.h
+@@ -0,0 +1,85 @@
++/* $Id: a.out.h,v 1.4 2004/03/30 19:35:04 ken-h Exp $ */
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_A_OUT_H__
++#define __NIOS2NOMMU_A_OUT_H__
++
++#define SPARC_PGSIZE 0x1000 /* Thanks to the sun4 architecture... */
++#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
++
++struct exec {
++ unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
++ unsigned char a_toolversion:7;
++ unsigned char a_machtype;
++ unsigned short a_info;
++ unsigned long a_text; /* length of text, in bytes */
++ unsigned long a_data; /* length of data, in bytes */
++ unsigned long a_bss; /* length of bss, in bytes */
++ unsigned long a_syms; /* length of symbol table, in bytes */
++ unsigned long a_entry; /* where program begins */
++ unsigned long a_trsize;
++ unsigned long a_drsize;
++};
++
++#define INIT_EXEC { \
++ .a_dynamic = 0, \
++ .a_toolversion = 0, \
++ .a_machtype = 0, \
++ .a_info = 0, \
++ .a_text = 0, \
++ .a_data = 0, \
++ .a_bss = 0, \
++ .a_syms = 0, \
++ .a_entry = 0, \
++ .a_trsize = 0, \
++ .a_drsize = 0, \
++}
++
++/* Where in the file does the text information begin? */
++#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
++
++/* Where do the Symbols start? */
++#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
++ (x).a_data + (x).a_trsize + \
++ (x).a_drsize)
++
++/* Where does text segment go in memory after being loaded? */
++#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \
++ ((x).a_entry < SPARC_PGSIZE)) ? \
++ 0 : SPARC_PGSIZE)
++
++/* And same for the data segment.. */
++#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
++ (N_TXTADDR(x) + (x).a_text) \
++ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
++
++#define N_TRSIZE(a) ((a).a_trsize)
++#define N_DRSIZE(a) ((a).a_drsize)
++#define N_SYMSIZE(a) ((a).a_syms)
++
++#ifdef __KERNEL__
++
++#define STACK_TOP TASK_SIZE
++
++#endif
++
++#endif /* __NIOS2NOMMU_A_OUT_H__ */
+--- linux/include/asm-nios2nommu/asm-macros.h
++++ linux/include/asm-nios2nommu/asm-macros.h
+@@ -0,0 +1,331 @@
++/*
++ * Macro used to simplify coding multi-line assembler.
++ * Some of the bit test macro can simplify down to one line
++ * depending on the mask value.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++/*
++ * ANDs reg2 with mask and places the result in reg1.
++ *
++ * You cannnot use the same register for reg1 & reg2.
++ */
++
++.macro ANDI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ movhi \reg1,%hi(\mask)
++ movui \reg1,%lo(\mask)
++ and \reg1,\reg1,\reg2
++ .else
++ andi \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ andhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * ORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro ORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ orhi \reg1,\reg2,%hi(\mask)
++ ori \reg1,\reg2,%lo(\mask)
++ .else
++ ori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ orhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * XORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro XORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ xorhi \reg1,\reg2,%hi(\mask)
++ xori \reg1,\reg1,%lo(\mask)
++ .else
++ xori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ xorhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * This is a support macro for BTBZ & BTBNZ. It checks
++ * the bit to make sure it is valid 32 value.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BT reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is non-zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBNZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTC reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ xori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ xorhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTS reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ ori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ orhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTR reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ andi \reg2,\reg2,%lo(~(1 << \bit))
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ andhi \reg2,\reg2,%lo(~(1 << (\bit - 16)))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBNZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBNZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBNZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the all the bits in the mask are zero it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the any of the bits in the mask are 1 it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBNZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Pushes reg onto the stack.
++ */
++
++.macro PUSH reg
++ addi sp,sp,-4
++ stw \reg,0(sp)
++.endm
++
++/*
++ * Pops the top of the stack into reg.
++ */
++
++.macro POP reg
++ ldw \reg,0(sp)
++ addi sp,sp,4
++.endm
++
++/*
++ * Clears reg
++ */
++
++.macro CLR reg
++ mov \reg,r0
++.endm
++
++/*
++ * The preprocessor macro does not work for
++ * the nios2 compiler. Undefine ENTRY and define
++ * a real assembler macro.
++ */
++#undef ENTRY
++#define ENTRY(name) ASM_ENTRY name
++
++.macro ASM_ENTRY name
++.globl \name
++__ALIGN
++ \name:
++.endm
+--- linux/include/asm-nios2nommu/atomic.h
++++ linux/include/asm-nios2nommu/atomic.h
+@@ -0,0 +1,190 @@
++//vic - add 'atomic_add/sub_return', 'atomic_add_negative'
++//vic from v850 architecture
++
++/* atomic.h:
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2001 Vic Phillips (vic@microtronix.com)
++ *
++ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2NOMMU_ATOMIC__
++#define __ARCH_NIOS2NOMMU_ATOMIC__
++
++#include <asm/system.h>
++
++typedef struct { int counter; } atomic_t;
++#define ATOMIC_INIT(i) { (i) }
++
++#define atomic_read(v) ((v)->counter)
++#define atomic_set(v, i) (((v)->counter) = i)
++
++
++extern __inline__ void atomic_add(int i, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter += i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_add_negative(int i, atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++
++ local_irq_save(flags);
++ v->counter += i;
++ result = (v->counter < 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_sub(int i, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++{
++ int result;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_inc(atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter += 1;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_inc_and_test(atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++
++ local_irq_save(flags);
++ v->counter += 1;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_dec(atomic_t *v)
++{
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_dec_and_test(atomic_t *v)
++{
++ int result;
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_inc_return(atomic_t *v)
++{
++ int result;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ result = ++v->counter;
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_dec_return(atomic_t *v)
++{
++ int result;
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = v->counter;
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_add_return (int i, volatile atomic_t *v)
++{
++ int res;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ res = v->counter + i;
++ v->counter = res;
++ local_irq_restore(flags);
++
++ return res;
++}
++
++static __inline__ int atomic_sub_return (int i, volatile atomic_t *v)
++{
++ int res;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ res = v->counter - i;
++ v->counter = res;
++ local_irq_restore(flags);
++
++ return res;
++}
++
++#define atomic_dec_return(v) atomic_sub_return(1,(v))
++#define atomic_inc_return(v) atomic_add_return(1,(v))
++
++/* Atomic operations are already serializing */
++#define smp_mb__before_atomic_dec() barrier()
++#define smp_mb__after_atomic_dec() barrier()
++#define smp_mb__before_atomic_inc() barrier()
++#define smp_mb__after_atomic_inc() barrier()
++
++
++#endif /* !(__ARCH_NIOS2NOMMU_ATOMIC__) */
++
++
+--- linux/include/asm-nios2nommu/bitops.h
++++ linux/include/asm-nios2nommu/bitops.h
+@@ -0,0 +1,472 @@
++#ifndef _ASM_NIOS_BITOPS_H_
++#define _ASM_NIOS_BITOPS_H_
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bitops.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef __KERNEL__
++// #include <linux/config.h>
++#include <linux/compiler.h>
++#include <asm/byteorder.h> /* swab32 */
++#include <asm/system.h>
++#endif
++
++/*
++ * Adapted to NIOS from generic bitops.h:
++ *
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents. You should
++ * recode these in the native assembly language, if at all possible.
++ * To guarantee atomicity, these routines call cli() and sti() to
++ * disable interrupts while they operate. (You have to provide inline
++ * routines to cli() and sti().)
++ *
++ * Also note, these routines assume that you have 32 bit integers.
++ * You will have to change this if you are trying to port Linux to the
++ * Alpha architecture or to a Cray. :-)
++ *
++ * C language equivalents written by Theodore Ts'o, 9/26/92
++ */
++
++/*
++ * Generic ffs().
++ */
++static inline int ffs(int x)
++{
++ int r = 1;
++
++ if (!x)
++ return 0;
++ if (!(x & 0xffff)) {
++ x >>= 16;
++ r += 16;
++ }
++ if (!(x & 0xff)) {
++ x >>= 8;
++ r += 8;
++ }
++ if (!(x & 0xf)) {
++ x >>= 4;
++ r += 4;
++ }
++ if (!(x & 3)) {
++ x >>= 2;
++ r += 2;
++ }
++ if (!(x & 1)) {
++ x >>= 1;
++ r += 1;
++ }
++ return r;
++}
++
++/*
++ * Generic __ffs().
++ */
++static inline int __ffs(int x)
++{
++ int r = 0;
++
++ if (!x)
++ return 0;
++ if (!(x & 0xffff)) {
++ x >>= 16;
++ r += 16;
++ }
++ if (!(x & 0xff)) {
++ x >>= 8;
++ r += 8;
++ }
++ if (!(x & 0xf)) {
++ x >>= 4;
++ r += 4;
++ }
++ if (!(x & 3)) {
++ x >>= 2;
++ r += 2;
++ }
++ if (!(x & 1)) {
++ x >>= 1;
++ r += 1;
++ }
++ return r;
++}
++
++/*
++ * fls: find last bit set.
++ */
++#define fls(x) generic_fls(x)
++
++
++/*
++ * Every architecture must define this function. It's the fastest
++ * way of searching a 140-bit bitmap where the first 100 bits are
++ * unlikely to be set. It's guaranteed that at least one of the 140
++ * bits is cleared.
++ */
++static inline int sched_find_first_bit(unsigned long *b)
++{
++ if (unlikely(b[0]))
++ return __ffs(b[0]);
++ if (unlikely(b[1]))
++ return __ffs(b[1]) + 32;
++ if (unlikely(b[2]))
++ return __ffs(b[2]) + 64;
++ if (b[3])
++ return __ffs(b[3]) + 96;
++ return __ffs(b[4]) + 128;
++}
++
++/*
++ * ffz = Find First Zero in word. Undefined if no zero exists,
++ * so code should check against ~0UL first..
++ */
++static __inline__ unsigned long ffz(unsigned long word)
++{
++ unsigned long result = 0;
++
++ while(word & 1) {
++ result++;
++ word >>= 1;
++ }
++ return result;
++}
++
++
++static __inline__ void set_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ *a |= mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ *a |= mask;
++}
++
++/*
++ * clear_bit() doesn't provide any barrier for the compiler.
++ */
++#define smp_mb__before_clear_bit() barrier()
++#define smp_mb__after_clear_bit() barrier()
++
++static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ *a &= ~mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __clear_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ *a &= ~mask;
++}
++
++static __inline__ void change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, flags;
++ unsigned long *ADDR = (unsigned long *) addr;
++
++ ADDR += nr >> 5;
++ mask = 1 << (nr & 31);
++ local_irq_save(flags);
++ *ADDR ^= mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask;
++ unsigned long *ADDR = (unsigned long *) addr;
++
++ ADDR += nr >> 5;
++ mask = 1 << (nr & 31);
++ *ADDR ^= mask;
++}
++
++static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a |= mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a |= mask;
++ return retval;
++}
++
++static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a &= ~mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a &= ~mask;
++ return retval;
++}
++
++static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a ^= mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a ^= mask;
++ return retval;
++}
++
++/*
++ * This routine doesn't need to be atomic.
++ */
++static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr)
++{
++ return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
++}
++
++static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ return ((mask & *a) != 0);
++}
++
++#define test_bit(nr,addr) \
++(__builtin_constant_p(nr) ? \
++ __constant_test_bit((nr),(unsigned long *)(addr)) : \
++ __test_bit((nr),(unsigned long *)(addr)))
++
++
++/* find_next_zero_bit() finds the first zero bit in a bit string of length
++ * 'size' bits, starting the search at bit 'offset'. This is largely based
++ * on Linus's ALPHA routines, which are pretty portable BTW.
++ */
++
++extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
++{
++ unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
++ unsigned long result = offset & ~31UL;
++ unsigned long tmp;
++
++ if (offset >= size)
++ return size;
++ size -= result;
++ offset &= 31UL;
++ if (offset) {
++ tmp = *(p++);
++ tmp |= ~0UL >> (32-offset);
++ if (size < 32)
++ goto found_first;
++ if (~tmp)
++ goto found_middle;
++ size -= 32;
++ result += 32;
++ }
++ while (size & ~31UL) {
++ if (~(tmp = *(p++)))
++ goto found_middle;
++ result += 32;
++ size -= 32;
++ }
++ if (!size)
++ return result;
++ tmp = *p;
++
++found_first:
++ tmp |= ~0UL << size;
++ if (tmp == ~0UL)
++ return result + size;
++found_middle:
++ return result + ffz(tmp);
++}
++
++/*
++ * Find next one bit in a bitmap reasonably efficiently.
++ */
++extern __inline__ unsigned long find_next_bit(const unsigned long *addr,
++ unsigned long size, unsigned long offset)
++{
++ unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
++ unsigned int result = offset & ~31UL;
++ unsigned int tmp;
++
++ if (offset >= size)
++ return size;
++ size -= result;
++ offset &= 31UL;
++ if (offset) {
++ tmp = *p++;
++ tmp &= ~0UL << offset;
++ if (size < 32)
++ goto found_first;
++ if (tmp)
++ goto found_middle;
++ size -= 32;
++ result += 32;
++ }
++ while (size >= 32) {
++ if ((tmp = *p++) != 0)
++ goto found_middle;
++ result += 32;
++ size -= 32;
++ }
++ if (!size)
++ return result;
++ tmp = *p;
++
++found_first:
++ tmp &= ~0UL >> (32 - size);
++ if (tmp == 0UL) /* Are any bits set? */
++ return result + size; /* Nope. */
++found_middle:
++ return result + __ffs(tmp);
++}
++
++/*
++ * hweightN: returns the hamming weight (i.e. the number
++ * of bits set) of a N-bit word
++ */
++
++#define hweight32(x) generic_hweight32(x)
++#define hweight16(x) generic_hweight16(x)
++#define hweight8(x) generic_hweight8(x)
++
++/* Linus sez that gcc can optimize the following correctly, we'll see if this
++ * holds on the Sparc as it does for the ALPHA.
++ */
++
++#define find_first_zero_bit(addr, size) \
++ find_next_zero_bit((addr), (size), 0)
++#define find_first_bit(addr, size) \
++ find_next_bit((addr), (size), 0)
++
++/* Now for the ext2 filesystem bit operations and helper routines.
++ *
++ * Both NIOS and ext2 are little endian, so these are the same as above.
++ */
++
++#define ext2_set_bit test_and_set_bit
++#define ext2_clear_bit test_and_clear_bit
++#define ext2_test_bit test_bit
++
++#define ext2_set_bit_atomic(lock, nr, addr) \
++ ({ \
++ int ret; \
++ spin_lock(lock); \
++ ret = ext2_set_bit((nr),(unsigned long *) (addr)); \
++ spin_unlock(lock); \
++ ret; \
++ })
++
++#define ext2_clear_bit_atomic(lock, nr, addr) \
++ ({ \
++ int ret; \
++ spin_lock(lock); \
++ ret = ext2_clear_bit((nr),(unsigned long *) (addr)); \
++ spin_unlock(lock); \
++ ret; \
++ })
++
++#define ext2_find_first_zero_bit find_first_zero_bit
++#define ext2_find_next_zero_bit find_next_zero_bit
++
++#endif /* _ASM_NIOS_BITOPS_H */
+--- linux/include/asm-nios2nommu/bootinfo.h
++++ linux/include/asm-nios2nommu/bootinfo.h
+@@ -0,0 +1,2 @@
++
++/* Nothing for nios2nommu */
+--- linux/include/asm-nios2nommu/bug.h
++++ linux/include/asm-nios2nommu/bug.h
+@@ -0,0 +1,48 @@
++#ifndef _NIOS2NOMMU_BUG_H
++#define _NIOS2NOMMU_BUG_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bug.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define BUG() do { \
++ printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
++} while (0)
++
++#define BUG_ON(condition) do { \
++ if (unlikely((condition)!=0)) \
++ BUG(); \
++} while(0)
++
++#define PAGE_BUG(page) do { \
++ BUG(); \
++} while (0)
++
++#define WARN_ON(condition) do { \
++ if (unlikely((condition)!=0)) { \
++ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
++ dump_stack(); \
++ } \
++} while (0)
++
++#endif
+--- linux/include/asm-nios2nommu/bugs.h
++++ linux/include/asm-nios2nommu/bugs.h
+@@ -0,0 +1,40 @@
++#ifndef __ASM_NIOS_BUGS_H
++#define __ASM_NIOS_BUGS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bugs.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1994 Linus Torvalds
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This is included by init/main.c to check for architecture-dependent bugs.
++ *
++ * Needs:
++ * void check_bugs(void);
++ */
++
++static void check_bugs(void)
++{
++}
++
++#endif
+--- linux/include/asm-nios2nommu/byteorder.h
++++ linux/include/asm-nios2nommu/byteorder.h
+@@ -0,0 +1,38 @@
++#ifndef __ASM_NIOS_BYTEORDER_H
++#define __ASM_NIOS_BYTEORDER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/byteorder.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/types.h>
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
++# define __BYTEORDER_HAS_U64__
++# define __SWAB_64_THRU_32__
++#endif
++
++#include <linux/byteorder/little_endian.h>
++
++#endif
++
+--- linux/include/asm-nios2nommu/cachectl.h
++++ linux/include/asm-nios2nommu/cachectl.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_CACHECTL_H
++#define _NIOS2NOMMU_CACHECTL_H
++
++/* Definitions for the cacheflush system call. */
++
++#define FLUSH_SCOPE_LINE 1 /* Flush a cache line */
++#define FLUSH_SCOPE_PAGE 2 /* Flush a page */
++#define FLUSH_SCOPE_ALL 3 /* Flush the whole cache -- superuser only */
++
++#define FLUSH_CACHE_DATA 1 /* Writeback and flush data cache */
++#define FLUSH_CACHE_INSN 2 /* Flush instruction cache */
++#define FLUSH_CACHE_BOTH 3 /* Flush both caches */
++
++#endif /* _NIOS2NOMMU_CACHECTL_H */
+--- linux/include/asm-nios2nommu/cacheflush.h
++++ linux/include/asm-nios2nommu/cacheflush.h
+@@ -0,0 +1,59 @@
++#ifndef _NIOS2NOMMU_CACHEFLUSH_H
++#define _NIOS2NOMMU_CACHEFLUSH_H
++
++/*
++ * Ported from m68knommu.
++ *
++ * (C) Copyright 2003, Microtronix Datacom Ltd.
++ * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/mm.h>
++
++extern void cache_push (unsigned long vaddr, int len);
++extern void dcache_push (unsigned long vaddr, int len);
++extern void icache_push (unsigned long vaddr, int len);
++extern void cache_push_all (void);
++extern void cache_clear (unsigned long paddr, int len);
++
++#define flush_cache_all() __flush_cache_all()
++#define flush_cache_mm(mm) do { } while (0)
++#define flush_cache_range(vma, start, end) cache_push(start, end - start)
++#define flush_cache_page(vma, vmaddr) do { } while (0)
++#define flush_dcache_range(start,end) dcache_push(start, end - start)
++#define flush_dcache_page(page) do { } while (0)
++#define flush_dcache_mmap_lock(mapping) do { } while (0)
++#define flush_dcache_mmap_unlock(mapping) do { } while (0)
++#define flush_icache_range(start,end) cache_push(start, end - start)
++#define flush_icache_page(vma,pg) do { } while (0)
++#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
++
++extern inline void __flush_cache_all(void)
++{
++ cache_push_all();
++}
++
++#endif /* _NIOS2NOMMU_CACHEFLUSH_H */
+--- linux/include/asm-nios2nommu/cache.h
++++ linux/include/asm-nios2nommu/cache.h
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2NOMMU_CACHE_H
++#define __ARCH_NIOS2NOMMU_CACHE_H
++
++#include <asm/nios.h>
++
++/* bytes per L1 cache line */
++#define L1_CACHE_BYTES nasys_icache_line_size /* this need to be at least 1 */
++
++
++#define __cacheline_aligned
++#define ____cacheline_aligned
++
++#endif
+--- linux/include/asm-nios2nommu/ChangeLog
++++ linux/include/asm-nios2nommu/ChangeLog
+@@ -0,0 +1,14 @@
++2004-06-29 Ken Hill <khill@microtronix.com>
++
++ * bitops.h (find_next_zero_bit): Fix problem with with masking for found_first
++ handling. The masking of the upper bits for size < 32 bits would set all
++ the bits to 1. Removing any zero's there may have been.
++
++2004-06-02 Ken Hill <khill@microtronix.com>
++
++ * processor.h (TASK_SIZE): Change na_sdram_end to nasys_program_mem_end to remove
++ dependancy on quartus memory component name.
++
++ * page.h (PAGE_OFFSET): Change na_sdram to nasys_program_mem to remove
++ dependancy on quartus memory component name.
++
+--- linux/include/asm-nios2nommu/checksum.h
++++ linux/include/asm-nios2nommu/checksum.h
+@@ -0,0 +1,320 @@
++#ifndef __NIOS2_CHECKSUM_H
++#define __NIOS2_CHECKSUM_H
++
++/* checksum.h: IP/UDP/TCP checksum routines on the NIOS.
++ *
++ * Copyright(C) 1995 Linus Torvalds
++ * Copyright(C) 1995 Miguel de Icaza
++ * Copyright(C) 1996 David S. Miller
++ * Copyright(C) 2001 Ken Hill
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * derived from:
++ * Alpha checksum c-code
++ * ix86 inline assembly
++ * Spar nommu
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++
++extern inline unsigned short csum_tcpudp_magic(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++" add %0, %3, %0\n"
++" bgeu %0, %3, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %4, %0\n"
++" bgeu %0, %4, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %5, %0\n"
++" bgeu %0, %5, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++/*
++ We need the carry from the addition of 16-bit
++ significant addition, so we zap out the low bits
++ in one half, zap out the high bits in another,
++ shift them both up to the top 16-bits of a word
++ and do the carry producing addition, finally
++ shift the result back down to the low 16-bits.
++
++ Actually, we can further optimize away two shifts
++ because we know the low bits of the original
++ value will be added to zero-only bits so cannot
++ affect the addition result nor the final carry
++ bit.
++*/
++" slli %1,%0, 16\n" /* Need a copy to fold with */
++ /* Bring the LOW 16 bits up */
++" add %0, %1, %0\n" /* add and set carry, neat eh? */
++" cmpltu r15, %0, %1\n" /* get remaining carry bit */
++" srli %0, %0, 16\n" /* shift back down the result */
++" add %0, %0, r15\n"
++" nor %0, %0, %0\n" /* negate */
++ : "=&r" (sum), "=&r" (saddr)
++ : "0" (sum), "1" (saddr), "r" (ntohl(len+proto)), "r" (daddr)
++ : "r15");
++ return ((unsigned short) sum);
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++ extern inline unsigned short from32to16(unsigned long x)
++ {
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r15, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r15\n"
++ : "=r" (x)
++ : "r" (x << 16), "0" (x)
++ : "r15");
++ return x;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern inline unsigned long do_csum(const unsigned char * buff, int len)
++{
++ int odd, count;
++ unsigned long result = 0;
++
++ barrier();
++ if (len <= 0)
++ goto out;
++ odd = 1 & (unsigned long) buff;
++ if (odd) {
++////result = *buff; // dgt: Big endian
++ result = *buff << 8; // dgt: Little endian
++
++ len--;
++ buff++;
++ }
++ count = len >> 1; /* nr of 16-bit words.. */
++ if (count) {
++ if (2 & (unsigned long) buff) {
++ result += *(unsigned short *) buff;
++ count--;
++ len -= 2;
++ buff += 2;
++ }
++ count >>= 1; /* nr of 32-bit words.. */
++ if (count) {
++ unsigned long carry = 0;
++ do {
++ unsigned long w = *(unsigned long *) buff;
++ count--;
++ buff += 4;
++ result += carry;
++ result += w;
++ carry = (w > result);
++ } while (count);
++ result += carry;
++ result = (result & 0xffff) + (result >> 16);
++ }
++ if (len & 2) {
++ result += *(unsigned short *) buff;
++ buff += 2;
++ }
++ }
++ if (len & 1)
++ result += *buff; /* This is little machine, byte is right */
++ result = from32to16(result);
++ if (odd)
++ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
++out:
++ return result;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/* ihl is always 5 or greater, almost always is 5, iph is always word
++ * aligned but can fail to be dword aligned very often.
++ */
++
++ extern inline unsigned short ip_fast_csum(const unsigned char *iph, unsigned int ihl)
++ {
++ unsigned int sum;
++
++ barrier();
++ __asm__ __volatile__(
++" andi r8, %1, 2\n" /* Remember original alignment */
++" ldw %0, (%1)\n" /* 16 or 32 bit boundary */
++" beq r8, r0, 1f\n" /* Aligned on 32 bit boundary, go */
++" srli %0, %0, 16\n" /* Get correct 16 bits */
++" addi %2, %2, -1\n" /* Take off for 4 bytes, pickup last 2 at end */
++" addi %1, %1, 2\n" /* Adjust pointer to 32 bit boundary */
++" br 2f\n"
++"1:\n"
++" addi %2, %2, -1\n"
++" addi %1, %1, 4\n" /* Bump ptr a long word */
++"2:\n"
++" ldw r9, (%1)\n"
++"1:\n"
++" add %0, r9, %0\n"
++" bgeu %0, r9, 2f\n"
++" addi %0, %0, 1\n"
++"2:\n"
++" addi %1, %1, 4\n"
++" addi %2, %2, -1\n"
++" ldw r9, (%1)\n"
++" bne %2, r0, 1b\n"
++" beq r8, r0, 1f\n" /* 32 bit boundary time to leave */
++" srli r9, r9, 16\n" /* 16 bit boundary, get correct 16 bits */
++" add %0, r9, %0\n"
++" bgeu %0, r9, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++" slli %2, %0, 16\n"
++" add %0, %2, %0\n"
++" cmpltu r8, %0, %2\n"
++" srli %0, %0, 16\n"
++" add %0, %0, r8\n"
++" nor %0, %0, %0\n"
++ : "=&r" (sum), "=&r" (iph), "=&r" (ihl)
++ : "1" (iph), "2" (ihl)
++ : "r8", "r9");
++ return sum;
++ barrier();
++ }
++
++/*these 2 functions are now in checksum.c */
++unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
++unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * the same as csum_partial_copy, but copies from user space.
++ *
++ * here even more important to align src and dst on a 32-bit (or even
++ * better 64-bit) boundary
++ */
++extern inline unsigned int
++csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
++{
++ barrier();
++ if (csum_err) *csum_err = 0;
++ memcpy(dst, src, len);
++ return csum_partial(dst, len, sum);
++ barrier();
++}
++
++#define csum_partial_copy_nocheck(src, dst, len, sum) \
++ csum_partial_copy ((src), (dst), (len), (sum))
++
++
++/*
++ * this routine is used for miscellaneous IP-like checksums, mainly
++ * in icmp.c
++ */
++
++extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
++{
++ barrier();
++ return ~from32to16(do_csum(buff,len));
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++#define csum_partial_copy_fromuser(s, d, l, w) \
++ csum_partial_copy((char *) (s), (d), (l), (w))
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/*
++ * Fold a partial checksum without adding pseudo headers
++ */
++extern __inline__ unsigned int csum_fold(unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r8\n"
++ "nor %0, %0, %0\n"
++ : "=r" (sum)
++ : "r" (sum << 16), "0" (sum)
++ : "r8");
++ return sum;
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %2, %0\n"
++ "cmpltu r8, %0, %2\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %3, %0\n"
++ "cmpltu r8, %0, %3\n"
++ "add %0, %0, r8\n" /* add carry */
++ : "=r" (sum), "=r" (saddr)
++ : "r" (daddr), "r" ( (ntohs(len)<<16) + (proto*256) ),
++ "0" (sum),
++ "1" (saddr)
++ : "r8");
++
++ return sum;
++ barrier();
++}
++
++
++#endif /* (__NIOS2_CHECKSUM_H) */
+--- linux/include/asm-nios2nommu/cprefix.h
++++ linux/include/asm-nios2nommu/cprefix.h
+@@ -0,0 +1,38 @@
++/* cprefix.h: This file is included by assembly source which needs
++ * to know what the c-label prefixes are. The newer versions
++ * of cpp that come with gcc predefine such things to help
++ * us out. The reason this stuff is needed is to make
++ * solaris compiles of the kernel work.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_CPREFIX_H
++#define __NIOS2_CPREFIX_H
++
++#define C_LABEL_PREFIX
++
++#define CONCAT(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a##b
++
++#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name)
++
++#endif /* !(__NIOS2_CPREFIX_H) */
+--- linux/include/asm-nios2nommu/cpumask.h
++++ linux/include/asm-nios2nommu/cpumask.h
+@@ -0,0 +1,28 @@
++/*
++ * All rights reserved.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_CPUMASK_H
++#define _ASM_NIOS2NOMMU_CPUMASK_H
++
++#include <asm-generic/cpumask.h>
++
++#endif /* _ASM_NIOS2NOMMU_CPUMASK_H */
+--- linux/include/asm-nios2nommu/cputime.h
++++ linux/include/asm-nios2nommu/cputime.h
+@@ -0,0 +1,31 @@
++/*
++ * cputime.h
++ * (C) Copyright 2004, Microtronix Datacom Ltd.
++ *
++ * Taken from m68knommu
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_CPUTIME_H
++#define __NIOS2NOMMU_CPUTIME_H
++
++#include <asm-generic/cputime.h>
++
++#endif /* __NIOS@NOMMU_CPUTIME_H */
+--- linux/include/asm-nios2nommu/current.h
++++ linux/include/asm-nios2nommu/current.h
+@@ -0,0 +1,39 @@
++#ifndef _NIOS2NOMMU_CURRENT_H
++#define _NIOS2NOMMU_CURRENT_H
++/*
++ * current.h
++ * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
++ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
++ * (C) Copyright 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/thread_info.h>
++
++struct task_struct;
++
++static inline struct task_struct *get_current(void)
++{
++ return(current_thread_info()->task);
++}
++
++#define current get_current()
++
++#endif /* _NIOS2NOMMU_CURRENT_H */
+--- linux/include/asm-nios2nommu/delay.h
++++ linux/include/asm-nios2nommu/delay.h
+@@ -0,0 +1,96 @@
++#ifndef _NIOS_DELAY_H
++#define _NIOS_DELAY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/delay.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/param.h>
++
++extern __inline__ void __delay(unsigned long loops)
++{
++ int dummy;
++
++ __asm__ __volatile__(
++ "1: \n\t"
++ " beq %0,zero,2f\n\t"
++ " addi %0, %0, -1\n\t"
++ " br 1b\n\t"
++ "2: \n\t"
++
++ : "=r" (dummy) /* Need output for optimizer */
++
++ : "0" (loops) /* %0 Input */
++ );
++}
++
++/*
++ * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so
++ * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32.
++ *
++ * The mul instruction gives us loops = (a * b) / 2^32.
++ * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226
++ * because this lets us support a wide range of HZ and
++ * loops_per_jiffy values without either a or b overflowing 2^32.
++ * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and
++ * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280
++ * (which corresponds to ~3800 bogomips at HZ = 100).
++ * -- paulus
++ */
++#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */
++#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */
++
++extern unsigned long loops_per_jiffy;
++
++extern __inline__ void __udelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 226));
++ __delay(loops);
++}
++
++extern __inline__ void __ndelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 5));
++ __delay(loops);
++}
++
++extern void __bad_udelay(void); /* deliberately undefined */
++extern void __bad_ndelay(void); /* deliberately undefined */
++
++#define udelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_UDELAY? __bad_udelay(): __udelay((n) * (19 * HZ))) : \
++ __udelay((n) * (19 * HZ)))
++
++#define ndelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_NDELAY? __bad_ndelay(): __ndelay((n) * HZ)) : \
++ __ndelay((n) * HZ))
++
++#define muldiv(a, b, c) (((a)*(b))/(c))
++
++#endif /* defined(_NIOS_DELAY_H) */
+--- linux/include/asm-nios2nommu/div64.h
++++ linux/include/asm-nios2nommu/div64.h
+@@ -0,0 +1,31 @@
++#ifndef __ASMNIOS_DIV64_H
++#define __ASMNIOS_DIV64_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/div64.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/div64.h>
++
++#endif
++
+--- linux/include/asm-nios2nommu/dma.h
++++ linux/include/asm-nios2nommu/dma.h
+@@ -0,0 +1,57 @@
++/* $Id: dma.h,v 1.6 2005/04/07 21:00:26 wentao Exp $
++ *
++ * Copyright 2004 (C) Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2_DMA_H
++#define _ASM_NIOS2_DMA_H
++
++#include <linux/kernel.h>
++#include <asm/asm-offsets.h>
++
++#define MAX_DMA_ADDRESS (LINUX_SDRAM_END)
++
++int request_dma(unsigned int, const char *);
++void free_dma(unsigned int);
++void enable_dma(unsigned int dmanr);
++void disable_dma(unsigned int dmanr);
++void set_dma_count(unsigned int dmanr, unsigned int count);
++int get_dma_residue(unsigned int dmanr);
++void nios2_set_dma_data_width(unsigned int dmanr, unsigned int width);
++
++void nios2_set_dma_handler(unsigned int dmanr, int (*handler)(void*, int), void* user);
++int nios2_request_dma(const char *);
++
++void nios2_set_dma_mode(unsigned int dmanr, unsigned int mode);
++void nios2_set_dma_rcon(unsigned int dmanr, unsigned int set);
++void nios2_set_dma_wcon(unsigned int dmanr, unsigned int set);
++void nios2_set_dma_raddr(unsigned int dmanr, unsigned int a);
++void nios2_set_dma_waddr(unsigned int dmanr, unsigned int a);
++
++static inline unsigned long claim_dma_lock(void)
++{
++}
++
++static inline void release_dma_lock(unsigned long flags)
++{
++}
++
++#endif /* !(_ASM_NIOS2_DMA_H) */
+--- linux/include/asm-nios2nommu/dma-mapping.h
++++ linux/include/asm-nios2nommu/dma-mapping.h
+@@ -0,0 +1,133 @@
++/*
++ * include/asm-nios2nommu/dma-mapping.h
++ *
++ * This file exists so that #include <dma-mapping.h> doesn't break anything.
++ */
++
++#ifndef _ASM_DMA_MAPPING_H
++#define _ASM_DMA_MAPPING_H
++
++#include <asm/scatterlist.h>
++#include <linux/mm.h>
++#include <asm/io.h>
++#include <asm/cacheflush.h>
++
++static inline void *dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, int flag)
++{
++ BUG();
++ return 0;
++}
++
++static inline void dma_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++/**
++ * dma_map_single - map a single buffer for streaming DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @cpu_addr: CPU direct mapped address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Ensure that any data held in the cache is appropriately discarded
++ * or written back.
++ *
++ * The device owns this memory once this call has completed. The CPU
++ * can regain ownership by calling dma_unmap_single() or
++ * dma_sync_single_for_cpu().
++ */
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ cache_push ((unsigned long)cpu_addr, size);
++ return virt_to_bus((unsigned long)cpu_addr);
++}
++
++/**
++ * dma_unmap_single - unmap a single buffer previously mapped
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @handle: DMA address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Unmap a single streaming mode DMA translation. The handle and size
++ * must match what was provided in the previous dma_map_single() call.
++ * All other usages are undefined.
++ *
++ * After this call, reads by the CPU to the buffer are guaranteed to see
++ * whatever the device wrote there.
++ */
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ cache_clear((unsigned long)bus_to_virt(handle), size);
++}
++
++/**
++ * 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
++ * above 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}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ * DMA address/length pairs than there are SG table elements.
++ * (for example via virtual mapping capabilities)
++ * The routine returns the number of addr/length pairs actually
++ * used, at most nents.
++ *
++ * Device ownership issues as mentioned above for dma_map_single are
++ * the same here.
++ */
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ int i;
++
++ for (i = 0; i < nents; i++, sg++) {
++ char *virt;
++
++ sg->dma_address = page_to_bus(sg->page) + sg->offset;
++ virt = page_address(sg->page) + sg->offset;
++ cache_push ((unsigned long)virt, sg->length);
++ }
++
++ return nents;
++}
++
++/**
++ * 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 map
++ * @dir: DMA transfer direction
++ *
++ * Unmap a set of streaming mode DMA translations.
++ * Again, CPU read rules concerning calls here are the same as for
++ * dma_unmap_single() above.
++ */
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ int i;
++
++ for (i = 0; i < nents; i++, sg++) {
++ char *virt;
++ virt = page_address(sg->page) + sg->offset;
++ cache_clear ((unsigned long)virt, sg->length);
++ }
++}
++#endif /* _ASM_DMA_MAPPING_H */
+--- linux/include/asm-nios2nommu/elf.h
++++ linux/include/asm-nios2nommu/elf.h
+@@ -0,0 +1,141 @@
++#ifndef __NIOS2_ELF_H
++#define __NIOS2_ELF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/elf.h
++ *
++ * Nio2 ELF relocation types
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ * Mar/18/2004 xwt NiosII relocation types added
++ *
++ ---------------------------------------------------------------------*/
++
++// #include <linux/config.h>
++#include <asm/ptrace.h>
++#include <asm/user.h>
++
++#define R_NIOS2_NONE 0
++#define R_NIOS2_S16 1
++#define R_NIOS2_U16 2
++#define R_NIOS2_PCREL16 3
++#define R_NIOS2_CALL26 4
++#define R_NIOS2_IMM5 5
++#define R_NIOS2_CACHE_OPX 6
++#define R_NIOS2_IMM6 7
++#define R_NIOS2_IMM8 8
++#define R_NIOS2_HI16 9
++#define R_NIOS2_LO16 10
++#define R_NIOS2_HIADJ16 11
++#define R_NIOS2_BFD_RELOC_32 12
++#define R_NIOS2_BFD_RELOC_16 13
++#define R_NIOS2_BFD_RELOC_8 14
++#define R_NIOS2_GPREL 15
++#define R_NIOS2_GNU_VTINHERIT 16
++#define R_NIOS2_GNU_VTENTRY 17
++#define R_NIOS2_UJMP 18
++#define R_NIOS2_CJMP 19
++#define R_NIOS2_CALLR 20
++#define R_NIOS2_ALIGN 21
++/* Keep this the last entry. */
++#define R_NIOS2_NUM 22
++
++typedef unsigned long elf_greg_t;
++
++#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++typedef unsigned long elf_fpregset_t;
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++#define elf_check_arch(x) \
++ ((x)->e_machine == EM_ALTERA_NIOS2)
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2LSB
++#define ELF_ARCH EM_ALTERA_NIOS2
++
++#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
++ use of this is to invoke "./ld.so someprog" to test out a new version of
++ the loader. We need to make sure that it is out of the way of the program
++ that it will "exec", and that there is sufficient room for the brk. */
++
++#define ELF_ET_DYN_BASE 0xD0000000UL
++
++/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
++ now struct_user_regs, they are different) */
++
++#define ELF_CORE_COPY_REGS(pr_reg, regs) \
++ /* Bleech. */ \
++ pr_reg[0] = regs->r1; \
++ pr_reg[1] = regs->r2; \
++ pr_reg[2] = regs->r3; \
++ pr_reg[3] = regs->r4; \
++ pr_reg[4] = regs->r5; \
++ pr_reg[5] = regs->r6; \
++ pr_reg[6] = regs->r7; \
++ pr_reg[7] = regs->r8; \
++ pr_reg[8] = regs->r9; \
++ pr_reg[9] = regs->r10; \
++ pr_reg[10] = regs->r11; \
++ pr_reg[11] = regs->r12; \
++ pr_reg[12] = regs->r13; \
++ pr_reg[13] = regs->r14; \
++ pr_reg[14] = regs->r15; \
++ pr_reg[23] = regs->sp; \
++ pr_reg[26] = regs->estatus; \
++ { \
++ struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \
++ pr_reg[15] = sw->r16; \
++ pr_reg[16] = sw->r17; \
++ pr_reg[17] = sw->r18; \
++ pr_reg[18] = sw->r19; \
++ pr_reg[19] = sw->r20; \
++ pr_reg[20] = sw->r21; \
++ pr_reg[21] = sw->r22; \
++ pr_reg[22] = sw->r23; \
++ pr_reg[24] = sw->fp; \
++ pr_reg[25] = sw->gp; \
++ }
++
++/* This yields a mask that user programs can use to figure out what
++ instruction set this cpu supports. */
++
++#define ELF_HWCAP (0)
++
++/* This yields a string that ld.so will use to load implementation
++ specific libraries for optimization. This is more specific in
++ intent than poking at uname or /proc/cpuinfo. */
++
++#define ELF_PLATFORM (NULL)
++
++#ifdef __KERNEL__
++#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
++#endif
++
++#endif
+--- linux/include/asm-nios2nommu/entry.h
++++ linux/include/asm-nios2nommu/entry.h
+@@ -0,0 +1,188 @@
++/*
++ * Hacked from m68knommu port.
++ *
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_ENTRY_H
++#define __NIOS2NOMMU_ENTRY_H
++
++#ifdef __ASSEMBLY__
++
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/asm-offsets.h>
++
++/*
++ * Stack layout in 'ret_from_exception':
++ *
++ * This allows access to the syscall arguments in registers r4-r8
++ *
++ * 0(sp) - r8
++ * 4(sp) - r9
++ * 8(sp) - r10
++ * C(sp) - r11
++ * 10(sp) - r12
++ * 14(sp) - r13
++ * 18(sp) - r14
++ * 1C(sp) - r15
++ * 20(sp) - r1
++ * 24(sp) - r2
++ * 28(sp) - r3
++ * 2C(sp) - r4
++ * 30(sp) - r5
++ * 34(sp) - r6
++ * 38(sp) - r7
++ * 3C(sp) - orig_r2
++ * 40(sp) - ra
++ * 44(sp) - fp
++ * 48(sp) - sp
++ * 4C(sp) - gp
++ * 50(sp) - estatus
++ * 54(sp) - status_extension
++ * 58(sp) - ea
++ *
++ */
++
++/* process bits for task_struct.flags */
++PF_TRACESYS_OFF = 3
++PF_TRACESYS_BIT = 5
++PF_PTRACED_OFF = 3
++PF_PTRACED_BIT = 4
++PF_DTRACE_OFF = 1
++PF_DTRACE_BIT = 5
++
++LENOSYS = 38
++
++/*
++ * This defines the normal kernel pt-regs layout.
++ *
++ */
++
++/*
++ * Standard Nios2 interrupt entry and exit macros.
++ * Must be called with interrupts disabled.
++ */
++.macro SAVE_ALL
++ movia r24,status_extension // Read status extension
++ ldw r24,0(r24)
++ andi r24,r24,PS_S_ASM
++ bne r24,r0,1f // In supervisor mode, already on kernel stack
++ movia r24,_current_thread // Switch to current kernel stack
++ ldw r24,0(r24) // using the thread_info
++ addi r24,r24,THREAD_SIZE_ASM-PT_REGS_SIZE
++ stw sp,PT_SP(r24) // Save user stack before changing
++ mov sp,r24
++ br 2f
++
++1: mov r24,sp
++ addi sp,sp,-PT_REGS_SIZE // Backup the kernel stack pointer
++ stw r24,PT_SP(sp)
++2: stw r1,PT_R1(sp)
++ stw r2,PT_R2(sp)
++ stw r3,PT_R3(sp)
++ stw r4,PT_R4(sp)
++ stw r5,PT_R5(sp)
++ stw r6,PT_R6(sp)
++ stw r7,PT_R7(sp)
++ stw r8,PT_R8(sp)
++ stw r9,PT_R9(sp)
++ stw r10,PT_R10(sp)
++ stw r11,PT_R11(sp)
++ stw r12,PT_R12(sp)
++ stw r13,PT_R13(sp)
++ stw r14,PT_R14(sp)
++ stw r15,PT_R15(sp)
++ stw r2,PT_ORIG_R2(sp)
++ stw ra,PT_RA(sp)
++ stw fp,PT_FP(sp)
++ stw gp,PT_GP(sp)
++ rdctl r24,estatus
++ stw r24,PT_ESTATUS(sp)
++ movia r24,status_extension // Read status extension
++ ldw r1,0(r24)
++ stw r1,PT_STATUS_EXTENSION(sp) // Store user/supervisor status
++ ORI32 r1,r1,PS_S_ASM // Set supervisor mode
++ stw r1,0(r24)
++ stw ea,PT_EA(sp)
++.endm
++
++.macro RESTORE_ALL
++ ldw r1,PT_STATUS_EXTENSION(sp) // Restore user/supervisor status
++ movia r24,status_extension
++ stw r1,0(r24)
++ ldw r1,PT_R1(sp) // Restore registers
++ ldw r2,PT_R2(sp)
++ ldw r3,PT_R3(sp)
++ ldw r4,PT_R4(sp)
++ ldw r5,PT_R5(sp)
++ ldw r6,PT_R6(sp)
++ ldw r7,PT_R7(sp)
++ ldw r8,PT_R8(sp)
++ ldw r9,PT_R9(sp)
++ ldw r10,PT_R10(sp)
++ ldw r11,PT_R11(sp)
++ ldw r12,PT_R12(sp)
++ ldw r13,PT_R13(sp)
++ ldw r14,PT_R14(sp)
++ ldw r15,PT_R15(sp)
++ ldw ra,PT_RA(sp)
++ ldw fp,PT_FP(sp)
++ ldw gp,PT_GP(sp)
++ ldw r24,PT_ESTATUS(sp)
++ wrctl estatus,r24
++ ldw ea,PT_EA(sp)
++ ldw sp,PT_SP(sp) // Restore sp last
++.endm
++
++.macro SAVE_SWITCH_STACK
++ addi sp,sp,-SWITCH_STACK_SIZE
++ stw r16,SW_R16(sp)
++ stw r17,SW_R17(sp)
++ stw r18,SW_R18(sp)
++ stw r19,SW_R19(sp)
++ stw r20,SW_R20(sp)
++ stw r21,SW_R21(sp)
++ stw r22,SW_R22(sp)
++ stw r23,SW_R23(sp)
++ stw fp,SW_FP(sp)
++ stw gp,SW_GP(sp)
++ stw ra,SW_RA(sp)
++.endm
++
++.macro RESTORE_SWITCH_STACK
++ ldw r16,SW_R16(sp)
++ ldw r17,SW_R17(sp)
++ ldw r18,SW_R18(sp)
++ ldw r19,SW_R19(sp)
++ ldw r20,SW_R20(sp)
++ ldw r21,SW_R21(sp)
++ ldw r22,SW_R22(sp)
++ ldw r23,SW_R23(sp)
++ ldw fp,SW_FP(sp)
++ ldw gp,SW_GP(sp)
++ ldw ra,SW_RA(sp)
++ addi sp,sp,SWITCH_STACK_SIZE
++.endm
++
++#endif /* __ASSEMBLY__ */
++#endif /* __NIOS2NOMMU_ENTRY_H */
+--- linux/include/asm-nios2nommu/errno.h
++++ linux/include/asm-nios2nommu/errno.h
+@@ -0,0 +1,6 @@
++#ifndef _NIOS2NOMMU_ERRNO_H
++#define _NIOS2NOMMU_ERRNO_H
++
++#include <asm-generic/errno.h>
++
++#endif /* _NIOS2NOMMU_ERRNO_H */
+--- linux/include/asm-nios2nommu/fcntl.h
++++ linux/include/asm-nios2nommu/fcntl.h
+@@ -0,0 +1,110 @@
++/*
++ * This file came from the m68k port.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_FCNTL_H
++#define _NIOS2_FCNTL_H
++
++/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
++ located on an ext2 file system */
++#define O_ACCMODE 0003
++#define O_RDONLY 00
++#define O_WRONLY 01
++#define O_RDWR 02
++#define O_CREAT 0100 /* not fcntl */
++#define O_EXCL 0200 /* not fcntl */
++#define O_NOCTTY 0400 /* not fcntl */
++#define O_TRUNC 01000 /* not fcntl */
++#define O_APPEND 02000
++#define O_NONBLOCK 04000
++#define O_NDELAY O_NONBLOCK
++#define O_SYNC 010000
++#define FASYNC 020000 /* fcntl, for BSD compatibility */
++#define O_DIRECTORY 040000 /* must be a directory */
++#define O_NOFOLLOW 0100000 /* don't follow links */
++#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
++#define O_LARGEFILE 0400000
++#define O_NOATIME 01000000
++
++#define F_DUPFD 0 /* dup */
++#define F_GETFD 1 /* get close_on_exec */
++#define F_SETFD 2 /* set/clear close_on_exec */
++#define F_GETFL 3 /* get file->f_flags */
++#define F_SETFL 4 /* set file->f_flags */
++#define F_GETLK 5
++#define F_SETLK 6
++#define F_SETLKW 7
++
++#define F_SETOWN 8 /* for sockets. */
++#define F_GETOWN 9 /* for sockets. */
++#define F_SETSIG 10 /* for sockets. */
++#define F_GETSIG 11 /* for sockets. */
++
++#define F_GETLK64 12 /* using 'struct flock64' */
++#define F_SETLK64 13
++#define F_SETLKW64 14
++
++/* for F_[GET|SET]FL */
++#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
++
++/* for posix fcntl() and lockf() */
++#define F_RDLCK 0
++#define F_WRLCK 1
++#define F_UNLCK 2
++
++/* for old implementation of bsd flock () */
++#define F_EXLCK 4 /* or 3 */
++#define F_SHLCK 8 /* or 4 */
++
++/* for leases */
++#define F_INPROGRESS 16
++
++/* operations for bsd flock(), also used by the kernel implementation */
++#define LOCK_SH 1 /* shared lock */
++#define LOCK_EX 2 /* exclusive lock */
++#define LOCK_NB 4 /* or'd with one of the above to prevent
++ blocking */
++#define LOCK_UN 8 /* remove lock */
++
++#define LOCK_MAND 32 /* This is a mandatory flock */
++#define LOCK_READ 64 /* ... Which allows concurrent read operations */
++#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
++#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
++
++struct flock {
++ short l_type;
++ short l_whence;
++ off_t l_start;
++ off_t l_len;
++ pid_t l_pid;
++};
++
++struct flock64 {
++ short l_type;
++ short l_whence;
++ loff_t l_start;
++ loff_t l_len;
++ pid_t l_pid;
++};
++
++#define F_LINUX_SPECIFIC_BASE 1024
++#endif /* _NIOS2_FCNTL_H */
+--- linux/include/asm-nios2nommu/flat.h
++++ linux/include/asm-nios2nommu/flat.h
+@@ -0,0 +1,126 @@
++/*
++ * include/asm-nios2nommu/flat.h -- uClinux bFLT relocations
++ *
++ * Copyright (C) 2004,05 Microtronix Datacom Ltd
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License. See the file COPYING in the main directory of this
++ * archive for more details.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#ifndef __NIOS2_FLAT_H__
++#define __NIOS2_FLAT_H__
++
++#define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
++
++/* The stack is 64-bit aligned for Nios II, so (sp - 1) shall
++ * be 64-bit aligned, where -1 is for argc
++ */
++#define flat_stack_align(sp) (sp = (unsigned long *)(((unsigned long)sp - 1) & (-8)))
++
++/* The uClibc port for Nios II expects the argc is followed by argv and envp */
++#define flat_argvp_envp_on_stack() 1
++
++#define flat_old_ram_flag(flags) (flags)
++
++/* We store the type of relocation in the top 4 bits of the `relval.' */
++
++/* Convert a relocation entry into an address. */
++static inline unsigned long
++flat_get_relocate_addr (unsigned long relval)
++{
++ return relval & 0x0fffffff; /* Mask out top 4-bits */
++}
++
++#define FLAT_NIOS2_RELOC_TYPE(relval) ((relval) >> 28)
++
++#define FLAT_NIOS2_R_32 0 /* Normal 32-bit reloc */
++#define FLAT_NIOS2_R_HI_LO 1 /* High 16-bits + low 16-bits field */
++#define FLAT_NIOS2_R_HIADJ_LO 2 /* High 16-bits adjust + low 16-bits field */
++#define FLAT_NIOS2_R_CALL26 4 /* Call imm26 */
++
++/* Extract the address to be relocated from the symbol reference at rp;
++ * relval is the raw relocation-table entry from which RP is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
++ unsigned long relval,
++ unsigned long flags)
++{
++ switch (FLAT_NIOS2_RELOC_TYPE(relval))
++ {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. The loader expect it in bigger endian */
++ return htonl(*rp);
++
++ case FLAT_NIOS2_R_HI_LO:
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ return htonl ((((rp[0] >> 6) & 0xFFFF) << 16 ) |
++ ((rp[1] >> 6) & 0xFFFF));
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ unsigned int low, high;
++ high = (rp[0] >> 6) & 0xFFFF;
++ low = (rp[1] >> 6) & 0xFFFF;
++
++ if ((low >> 15) & 1) high--;
++
++ return htonl ((high << 16 ) | low );
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the 26-bit immediate value is actually 28-bit */
++ return htonl(((*rp) >> 6) << 2);
++
++ default:
++ return ~0; /* bogus value */
++ }
++}
++
++/* Insert the address addr into the symbol reference at rp;
++ * relval is the raw relocation-table entry from which rp is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
++ unsigned long relval)
++{
++ unsigned long exist_val;
++ switch (FLAT_NIOS2_RELOC_TYPE (relval)) {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. */
++ *rp = addr;
++ break;
++
++ case FLAT_NIOS2_R_HI_LO:
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | (addr >> 16)) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ unsigned int high = (addr >> 16);
++ if ((addr >> 15) & 1)
++ high = (high + 1) & 0xFFFF;
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | high) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the opcode of CALL is 0, so just store the value */
++ *rp = ((addr >> 2) << 6);
++ break;
++ }
++}
++
++#endif /* __NIOS2_FLAT_H__ */
+--- linux/include/asm-nios2nommu/hardirq.h
++++ linux/include/asm-nios2nommu/hardirq.h
+@@ -0,0 +1,53 @@
++/*
++ * Ported from m68knommu
++ *
++ * Copyright (C) 2003, Microtronix Datacom Ltd.
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HARDIRQ_H
++#define __NIOS2_HARDIRQ_H
++
++// #include <linux/config.h>
++#include <linux/cache.h>
++#include <linux/threads.h>
++
++typedef struct {
++ unsigned int __softirq_pending;
++} ____cacheline_aligned irq_cpustat_t;
++
++#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
++
++#define HARDIRQ_BITS 8
++
++/*
++ * The hardirq mask has to be large enough to have
++ * space for potentially all IRQ sources in the system
++ * nesting on a single CPU:
++ */
++#if (1 << HARDIRQ_BITS) < NR_IRQS
++# error HARDIRQ_BITS is too low!
++#endif
++
++#ifdef CONFIG_SMP
++# error nios2nommu SMP is not available
++#endif /* CONFIG_SMP */
++
++#endif /* __NIOS2_HARDIRQ_H */
+--- linux/include/asm-nios2nommu/hdreg.h
++++ linux/include/asm-nios2nommu/hdreg.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2002 Wentau Xu (www.microtronix.com)
++ * copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HDREG_H
++#define __NIOS2_HDREG_H
++
++typedef unsigned long ide_ioreg_t;
++
++#endif /* __NIOS2_HDREG_H */
+--- linux/include/asm-nios2nommu/hw_irq.h
++++ linux/include/asm-nios2nommu/hw_irq.h
+@@ -0,0 +1,16 @@
++#ifndef _ASM_HW_IRQ_H
++#define _ASM_HW_IRQ_H
++
++/*
++ * linux/include/asm/hw_irq.h
++ *
++ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
++ *
++ * moved some of the old arch/i386/kernel/irq.h to here. VY
++ *
++ * IRQ/IPI changes taken from work by Thomas Radke
++ * <tomsoft@informatik.tu-chemnitz.de>
++ */
++
++
++#endif /* _ASM_HW_IRQ_H */
+--- linux/include/asm-nios2nommu/ide.h
++++ linux/include/asm-nios2nommu/ide.h
+@@ -0,0 +1,47 @@
++/*
++ * linux/include/asm-niosnommu2/ide.h
++ *
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASMNIOS2_IDE_H
++#define __ASMNIOS2_IDE_H
++
++#ifdef __KERNEL__
++#undef MAX_HWIFS /* we're going to force it */
++
++#ifndef MAX_HWIFS
++#define MAX_HWIFS 1
++#endif
++
++#define IDE_ARCH_OBSOLETE_INIT
++#define IDE_ARCH_OBSOLETE_DEFAULTS
++#define ide_default_io_base(i) ((unsigned long)na_ide_ide)
++#define ide_default_irq(b) (na_ide_ide_irq)
++#define ide_init_default_irq(base) ide_default_irq(base)
++#define ide_default_io_ctl(base) ((base) + (0xE*4))
++
++#include <asm-generic/ide_iops.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASMNIOS2_IDE_H */
+--- linux/include/asm-nios2nommu/init.h
++++ linux/include/asm-nios2nommu/init.h
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++#error "<asm/init.h> should never be used - use <linux/init.h> instead"
+--- linux/include/asm-nios2nommu/ioctl.h
++++ linux/include/asm-nios2nommu/ioctl.h
+@@ -0,0 +1,100 @@
++/* $Id: ioctl.h,v 1.3 2004/02/12 23:06:40 ken-h Exp $
++ *
++ * linux/ioctl.h for Linux by H.H. Bergman.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_IOCTL_H
++#define _NIOS2_IOCTL_H
++
++/* ioctl command encoding: 32 bits total, command in lower 16 bits,
++ * size of the parameter structure in the lower 14 bits of the
++ * upper 16 bits.
++ * Encoding the size of the parameter structure in the ioctl request
++ * is useful for catching programs compiled with old versions
++ * and to avoid overwriting user space outside the user buffer area.
++ * The highest 2 bits are reserved for indicating the ``access mode''.
++ * NOTE: This limits the max parameter size to 16kB -1 !
++ */
++
++/*
++ * I don't really have any idea about what this should look like, so
++ * for the time being, this is heavily based on the PC definitions.
++ */
++
++/*
++ * The following is for compatibility across the various Linux
++ * platforms. The i386 ioctl numbering scheme doesn't really enforce
++ * a type field. De facto, however, the top 8 bits of the lower 16
++ * bits are indeed used as a type field, so we might just as well make
++ * this explicit here. Please be sure to use the decoding macros
++ * below from now on.
++ */
++#define _IOC_NRBITS 8
++#define _IOC_TYPEBITS 8
++#define _IOC_SIZEBITS 14
++#define _IOC_DIRBITS 2
++
++#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
++#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
++#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
++#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
++
++#define _IOC_NRSHIFT 0
++#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
++#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
++#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
++
++/*
++ * Direction bits.
++ */
++#define _IOC_NONE 0U
++#define _IOC_WRITE 1U
++#define _IOC_READ 2U
++
++#define _IOC(dir,type,nr,size) \
++ (((dir) << _IOC_DIRSHIFT) | \
++ ((type) << _IOC_TYPESHIFT) | \
++ ((nr) << _IOC_NRSHIFT) | \
++ ((size) << _IOC_SIZESHIFT))
++
++/* used to create numbers */
++#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
++#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
++#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
++#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
++
++/* used to decode ioctl numbers.. */
++#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
++#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
++#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
++#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
++
++/* ...and for the drivers/sound files... */
++
++#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
++#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
++#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
++#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
++#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
++
++#endif /* _NIOS2_IOCTL_H */
+--- linux/include/asm-nios2nommu/ioctls.h
++++ linux/include/asm-nios2nommu/ioctls.h
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2_IOCTLS_H__
++#define __ARCH_NIOS2_IOCTLS_H__
++
++#include <asm/ioctl.h>
++
++/* 0x54 is just a magic number to make these relatively unique ('T') */
++
++#define TCGETS 0x5401
++#define TCSETS 0x5402
++#define TCSETSW 0x5403
++#define TCSETSF 0x5404
++#define TCGETA 0x5405
++#define TCSETA 0x5406
++#define TCSETAW 0x5407
++#define TCSETAF 0x5408
++#define TCSBRK 0x5409
++#define TCXONC 0x540A
++#define TCFLSH 0x540B
++#define TIOCEXCL 0x540C
++#define TIOCNXCL 0x540D
++#define TIOCSCTTY 0x540E
++#define TIOCGPGRP 0x540F
++#define TIOCSPGRP 0x5410
++#define TIOCOUTQ 0x5411
++#define TIOCSTI 0x5412
++#define TIOCGWINSZ 0x5413
++#define TIOCSWINSZ 0x5414
++#define TIOCMGET 0x5415
++#define TIOCMBIS 0x5416
++#define TIOCMBIC 0x5417
++#define TIOCMSET 0x5418
++#define TIOCGSOFTCAR 0x5419
++#define TIOCSSOFTCAR 0x541A
++#define FIONREAD 0x541B
++#define TIOCINQ FIONREAD
++#define TIOCLINUX 0x541C
++#define TIOCCONS 0x541D
++#define TIOCGSERIAL 0x541E
++#define TIOCSSERIAL 0x541F
++#define TIOCPKT 0x5420
++#define FIONBIO 0x5421
++#define TIOCNOTTY 0x5422
++#define TIOCSETD 0x5423
++#define TIOCGETD 0x5424
++#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
++#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
++#define TIOCSBRK 0x5427 /* BSD compatibility */
++#define TIOCCBRK 0x5428 /* BSD compatibility */
++#define TIOCGSID 0x5429 /* Return the session ID of FD */
++#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
++#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
++
++#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
++#define FIOCLEX 0x5451
++#define FIOASYNC 0x5452
++#define TIOCSERCONFIG 0x5453
++#define TIOCSERGWILD 0x5454
++#define TIOCSERSWILD 0x5455
++#define TIOCGLCKTRMIOS 0x5456
++#define TIOCSLCKTRMIOS 0x5457
++#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
++#define TIOCSERGETLSR 0x5459 /* Get line status register */
++#define TIOCSERGETMULTI 0x545A /* Get multiport config */
++#define TIOCSERSETMULTI 0x545B /* Set multiport config */
++
++#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
++#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
++#define FIOQSIZE 0x545E
++
++/* Used for packet mode */
++#define TIOCPKT_DATA 0
++#define TIOCPKT_FLUSHREAD 1
++#define TIOCPKT_FLUSHWRITE 2
++#define TIOCPKT_STOP 4
++#define TIOCPKT_START 8
++#define TIOCPKT_NOSTOP 16
++#define TIOCPKT_DOSTOP 32
++
++#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
++
++#endif /* __ARCH_NIOS2_IOCTLS_H__ */
+--- linux/include/asm-nios2nommu/io.h
++++ linux/include/asm-nios2nommu/io.h
+@@ -0,0 +1,240 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_IO_H
++#define __NIOS2_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/kernel.h>
++
++#include <asm/page.h> /* IO address mapping routines need this */
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++extern void insw(unsigned long port, void *dst, unsigned long count);
++extern void outsw(unsigned long port, void *src, unsigned long count);
++extern void insl(unsigned long port, void *dst, unsigned long count);
++extern void outsl(unsigned long port, void *src, unsigned long count);
++
++
++/*
++ * readX/writeX() are used to access memory mapped devices. On some
++ * architectures the memory mapped IO stuff needs to be accessed
++ * differently. On the Nios architecture, we just read/write the
++ * memory location directly.
++ */
++
++#define readb(addr) \
++({ \
++ unsigned char __res;\
++ __asm__ __volatile__( \
++ "ldbuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readw(addr) \
++({ \
++ unsigned short __res;\
++ __asm__ __volatile__( \
++ "ldhuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readl(addr) \
++({ \
++ unsigned int __res;\
++ __asm__ __volatile__( \
++ "ldwio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define writeb(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stbio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writew(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "sthio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writel(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stwio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define __raw_readb readb
++#define __raw_readw readw
++#define __raw_readl readl
++#define __raw_writeb writeb
++#define __raw_writew writew
++#define __raw_writel writel
++
++#define mmiowb()
++
++/*
++ * make the short names macros so specific devices
++ * can override them as required
++ */
++
++#define memset_io(addr,c,len) memset((void *)(((unsigned int)(addr)) | 0x80000000),(c),(len))
++#define memcpy_fromio(to,from,len) memcpy((to),(void *)(((unsigned int)(from)) | 0x80000000),(len))
++#define memcpy_toio(to,from,len) memcpy((void *)(((unsigned int)(to)) | 0x80000000),(from),(len))
++
++#define inb(addr) readb(addr)
++#define inw(addr) readw(addr)
++#define inl(addr) readl(addr)
++
++#define outb(x,addr) ((void) writeb(x,addr))
++#define outw(x,addr) ((void) writew(x,addr))
++#define outl(x,addr) ((void) writel(x,addr))
++
++#define inb_p(addr) inb(addr)
++#define inw_p(addr) inw(addr)
++#define inl_p(addr) inl(addr)
++
++#define outb_p(x,addr) outb(x,addr)
++#define outw_p(x,addr) outw(x,addr)
++#define outl_p(x,addr) outl(x,addr)
++
++
++
++extern inline void insb(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)dst;
++ while (count--)
++ *p++ = inb(port);
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _insw(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)dst;
++ while (count--)
++ *p++ = inw(port);
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned destination pointer */
++extern inline void _insl(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)dst;
++ while (count--)
++ *p++ = inl(port);
++}
++
++extern inline void outsb(unsigned long port, void *src, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)src;
++ while (count--)
++ outb( *p++, port );
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _outsw(unsigned long port, void *src, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)src;
++ while (count--)
++ outw( *p++, port );
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned source pointer */
++extern inline void _outsl(unsigned long port, void *src, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)src;
++ while (count--)
++ outl( *p++, port );
++}
++
++
++
++extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
++ int bus, int rdonly)
++{
++ return;
++}
++
++//vic - copied from m68knommu
++
++/* Values for nocacheflag and cmode */
++#define IOMAP_FULL_CACHING 0
++#define IOMAP_NOCACHE_SER 1
++#define IOMAP_NOCACHE_NONSER 2
++#define IOMAP_WRITETHROUGH 3
++
++extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
++extern void __iounmap(void *addr, unsigned long size);
++
++extern inline void *ioremap(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
++}
++extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
++}
++
++extern void iounmap(void *addr);
++
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define dma_cache_inv(_start,_size) do { } while (0)
++#define dma_cache_wback(_start,_size) do { } while (0)
++#define dma_cache_wback_inv(_start,_size) do { } while (0)
++
++/* Pages to physical address... */
++#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
++#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#endif /* __KERNEL__ */
++
++#endif /* !(__NIOS2_IO_H) */
++
+--- linux/include/asm-nios2nommu/ipcbuf.h
++++ linux/include/asm-nios2nommu/ipcbuf.h
+@@ -0,0 +1,49 @@
++#ifndef __NIOS2_IPCBUF_H__
++#define __NIOS2_IPCBUF_H__
++
++/* Copied from asm-m68k/ipcbuf.h
++ * The user_ipc_perm structure for Nios architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 32-bit mode_t and seq
++ * - 2 miscellaneous 32-bit values
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++struct ipc64_perm
++{
++ __kernel_key_t key;
++ __kernel_uid32_t uid;
++ __kernel_gid32_t gid;
++ __kernel_uid32_t cuid;
++ __kernel_gid32_t cgid;
++ __kernel_mode_t mode;
++ unsigned short __pad1;
++ unsigned short seq;
++ unsigned short __pad2;
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* __NIOS2_IPCBUF_H__ */
+--- linux/include/asm-nios2nommu/ipc.h
++++ linux/include/asm-nios2nommu/ipc.h
+@@ -0,0 +1,51 @@
++#ifndef __NIOS2_IPC_H__
++#define __NIOS2_IPC_H__
++
++/* Copied from sparc version
++ * These are used to wrap system calls on the Nios.
++ *
++ * See arch/niosnommu/kernel/sys_nios.c for ugly details..
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++struct ipc_kludge {
++ struct msgbuf *msgp;
++ long msgtyp;
++};
++
++#define SEMOP 1
++#define SEMGET 2
++#define SEMCTL 3
++#define MSGSND 11
++#define MSGRCV 12
++#define MSGGET 13
++#define MSGCTL 14
++#define SHMAT 21
++#define SHMDT 22
++#define SHMGET 23
++#define SHMCTL 24
++
++/* Used by the DIPC package, try and avoid reusing it */
++#define DIPC 25
++
++#define IPCCALL(version,op) ((version)<<16 | (op))
++
++#endif
+--- linux/include/asm-nios2nommu/irq.h
++++ linux/include/asm-nios2nommu/irq.h
+@@ -0,0 +1,182 @@
++/*
++ * 21Mar2001 1.1 dgt/microtronix
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_IRQ_H_
++#define _NIOS2NOMMU_IRQ_H_
++
++extern void disable_irq(unsigned int);
++extern void enable_irq(unsigned int);
++
++// #include <linux/config.h>
++#include <linux/interrupt.h>
++
++#define SYS_IRQS 32
++#define NR_IRQS SYS_IRQS
++
++/*
++ * Interrupt source definitions
++ * General interrupt sources are the level 1-7.
++ * Adding an interrupt service routine for one of these sources
++ * results in the addition of that routine to a chain of routines.
++ * Each one is called in succession. Each individual interrupt
++ * service routine should determine if the device associated with
++ * that routine requires service.
++ */
++
++#define IRQ01 (1) /* level 1 interrupt */
++#define IRQ02 (2) /* level 2 interrupt */
++#define IRQ03 (3) /* level 3 interrupt */
++#define IRQ04 (4) /* level 4 interrupt */
++#define IRQ05 (5) /* level 5 interrupt */
++#define IRQ06 (6) /* level 6 interrupt */
++#define IRQ07 (7) /* level 7 interrupt */
++#define IRQ08 (8) /* level 8 interrupt */
++#define IRQ09 (9) /* level 9 interrupt */
++#define IRQ0A (10) /* level 10 interrupt */
++#define IRQ0B (11) /* level 11 interrupt */
++#define IRQ0C (12) /* level 12 interrupt */
++#define IRQ0D (13) /* level 13 interrupt */
++#define IRQ0E (14) /* level 14 interrupt */
++#define IRQ0F (15) /* level 15 interrupt */
++#define IRQ10 (16) /* level 16 interrupt */
++#define IRQ12 (17) /* level 17 interrupt */
++#define IRQ13 (18) /* level 18 interrupt */
++#define IRQ14 (19) /* level 19 interrupt */
++#define IRQ15 (20) /* level 20 interrupt */
++#define IRQ16 (21) /* level 21 interrupt */
++#define IRQ17 (22) /* level 22 interrupt */
++#define IRQ18 (23) /* level 23 interrupt */
++#define IRQ19 (24) /* level 24 interrupt */
++#define IRQ1A (25) /* level 25 interrupt */
++#define IRQ1B (26) /* level 26 interrupt */
++#define IRQ1C (27) /* level 27 interrupt */
++#define IRQ1D (28) /* level 28 interrupt */
++#define IRQ1E (29) /* level 29 interrupt */
++#define IRQ1F (30) /* level 30 interrupt */
++#define IRQ20 (31) /* level 31 interrupt */
++#define IRQ21 (32) /* level 32 interrupt */
++
++#define IRQMAX IRQ21
++
++/*
++ * "Generic" interrupt sources
++ */
++
++/*
++ * Machine specific interrupt sources.
++ *
++ * Adding an interrupt service routine for a source with this bit
++ * set indicates a special machine specific interrupt source.
++ * The machine specific files define these sources.
++ *
++ * Removed, they are not used by any one.
++ */
++
++/*
++ * various flags for request_irq()
++ */
++#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
++#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
++#define IRQ_FLG_FAST (0x0004)
++#define IRQ_FLG_SLOW (0x0008)
++#define IRQ_FLG_STD (0x8000) /* internally used */
++
++/*
++ * Functions to set and clear the interrupt mask.
++ */
++
++/*
++ * Use a zero to clean the bit.
++ */
++static inline void clrimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "and r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * Use a one to set the bit.
++ */
++static inline void setimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "or r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * This structure is used to chain together the ISRs for a particular
++ * interrupt source (if it supports chaining).
++ */
++typedef struct irq_node {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++ struct irq_node *next;
++} irq_node_t;
++
++/*
++ * This function returns a new irq_node_t
++ */
++extern irq_node_t *new_irq_node(void);
++
++/*
++ * This structure has only 4 elements for speed reasons
++ */
++typedef struct irq_handler {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++} irq_handler_t;
++
++/* count of spurious interrupts */
++extern volatile unsigned int num_spurious;
++
++#define disable_irq_nosync(i) disable_irq(i)
++
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#endif /* _NIOS2NOMMU_IRQ_H_ */
+--- linux/include/asm-nios2nommu/kmap_types.h
++++ linux/include/asm-nios2nommu/kmap_types.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_KMAP_TYPES_H
++#define _ASM_KMAP_TYPES_H
++
++enum km_type {
++ KM_BOUNCE_READ,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ KM_TYPE_NR
++};
++
++#endif
+--- linux/include/asm-nios2nommu/linkage.h
++++ linux/include/asm-nios2nommu/linkage.h
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASM_LINKAGE_H
++#define __ASM_LINKAGE_H
++
++#define __ALIGN .align 3
++#define __ALIGN_STR ".align 3"
++
++#endif
+--- linux/include/asm-nios2nommu/linux_logo.h
++++ linux/include/asm-nios2nommu/linux_logo.h
+@@ -0,0 +1,953 @@
++/* $Id: linux_logo.h,v 1.3 2004/02/12 23:06:40 ken-h Exp $
++ * include/asm-nios/linux_logo.h: This is a linux logo
++ * to be displayed on boot.
++ *
++ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
++ * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
++ * Copyright (C) 2004 Micrtronix Datacom Ltd.
++ *
++ * You can put anything here, but:
++ * LINUX_LOGO_COLORS has to be less than 224
++ * image size has to be 80x80
++ * values have to start from 0x20
++ * (i.e. RGB(linux_logo_red[0],
++ * linux_logo_green[0],
++ * linux_logo_blue[0]) is color 0x20)
++ * BW image has to be 80x80 as well, with MS bit
++ * on the left
++ * Serial_console ascii image can be any size,
++ * but should contain %s to display the version
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/init.h>
++#include <linux/version.h>
++
++#define linux_logo_banner "Linux/NIOS2 version " UTS_RELEASE
++
++#define __HAVE_ARCH_LINUX_LOGO
++#define __HAVE_ARCH_LINUX_LOGO16
++
++#define LINUX_LOGO_COLORS 221
++
++#ifdef INCLUDE_LINUX_LOGO_DATA
++
++unsigned char linux_logo_red[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79,
++ 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7,
++ 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8,
++ 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6,
++ 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee,
++ 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c,
++ 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e,
++ 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c,
++ 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfe,
++ 0xf6, 0xec, 0xfe, 0xd2, 0xea, 0xf5, 0xf2, 0xf2,
++ 0xe9, 0xee, 0xf6, 0xf2, 0xee, 0xf6, 0xda, 0xd4,
++ 0xfa, 0xca, 0xf2, 0xf6, 0xfe, 0xf2, 0xda, 0xe4,
++ 0xf6, 0xdd, 0xf2, 0xee, 0xfa, 0xf0, 0x12, 0x4a,
++ 0xd6, 0xf2, 0x8e, 0xf2, 0xf6, 0xf6, 0xb5, 0xf1,
++ 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, 0x9a,
++ 0x2e, 0xd2, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62,
++ 0xda, 0xee, 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xe0,
++ 0xae, 0xbe, 0xce, 0xe2, 0xa3, 0x8e, 0x6d, 0x8e,
++ 0x32, 0xaf, 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82,
++ 0x7a, 0x82, 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86,
++ 0x6a, 0x52, 0x59, 0x64, 0x5e,
++};
++
++unsigned char linux_logo_green[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c,
++ 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae,
++ 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8,
++ 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda,
++ 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca,
++ 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76,
++ 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46,
++ 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b,
++ 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfa,
++ 0xea, 0xd7, 0xf6, 0xbc, 0xda, 0xde, 0xda, 0xe6,
++ 0xca, 0xd8, 0xea, 0xe0, 0xcc, 0xf2, 0xce, 0xb2,
++ 0xee, 0xa2, 0xd6, 0xe6, 0xf6, 0xd7, 0xc5, 0xb8,
++ 0xc6, 0xb9, 0xce, 0xde, 0xce, 0xc6, 0x0e, 0x36,
++ 0xae, 0xbe, 0x86, 0xba, 0xbe, 0xe6, 0x8e, 0xc4,
++ 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, 0x7a,
++ 0x20, 0xc6, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46,
++ 0xce, 0xd6, 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa6,
++ 0x87, 0x96, 0xa2, 0xd6, 0x85, 0x7a, 0x6a, 0x6e,
++ 0x22, 0x76, 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53,
++ 0x66, 0x62, 0x42, 0x50, 0x56, 0x42, 0x56, 0x56,
++ 0x56, 0x3e, 0x51, 0x52, 0x56,
++};
++
++unsigned char linux_logo_blue[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08,
++ 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f,
++ 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e,
++ 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c,
++ 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f,
++ 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a,
++ 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e,
++ 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b,
++ 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xea,
++ 0xb6, 0x7c, 0xda, 0x8e, 0xa6, 0x87, 0x66, 0xb6,
++ 0x81, 0x6a, 0xc6, 0x9a, 0x5b, 0xd2, 0xb6, 0x6a,
++ 0xca, 0x45, 0x92, 0xb2, 0xca, 0x52, 0x8a, 0x3e,
++ 0x2e, 0x66, 0x66, 0xae, 0x3e, 0x47, 0x06, 0x0e,
++ 0x52, 0x36, 0x6a, 0x0e, 0x0e, 0xbe, 0x2c, 0x0e,
++ 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, 0x2e,
++ 0x06, 0x9e, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06,
++ 0x9e, 0xae, 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x0a,
++ 0x32, 0x2e, 0x2a, 0xb2, 0x43, 0x48, 0x5f, 0x2e,
++ 0x06, 0x06, 0x07, 0x24, 0x06, 0x32, 0x06, 0x06,
++ 0x46, 0x2e, 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06,
++ 0x3a, 0x22, 0x42, 0x34, 0x42,
++};
++
++unsigned char linux_logo[] __initdata = {
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
++ 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++ 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d,
++ 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24,
++ 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c,
++ 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31,
++ 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34,
++ 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36,
++ 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22,
++ 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25,
++ 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22,
++ 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36,
++ 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36,
++ 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23,
++ 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21,
++ 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b,
++ 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26,
++ 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d,
++ 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32,
++ 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a,
++ 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b,
++ 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37,
++ 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58,
++ 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35,
++ 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
++ 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22,
++ 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67,
++ 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36,
++ 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e,
++ 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73,
++ 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78,
++ 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79,
++ 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c,
++ 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24,
++ 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71,
++ 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36,
++ 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21,
++ 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89,
++ 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36,
++ 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21,
++ 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e,
++ 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23,
++ 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22,
++ 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63,
++ 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c,
++ 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51,
++ 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21,
++ 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97,
++ 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98,
++ 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39,
++ 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32,
++ 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50,
++ 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48,
++ 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23,
++ 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98,
++ 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50,
++ 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b,
++ 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b,
++ 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34,
++ 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52,
++ 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c,
++ 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c,
++ 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b,
++ 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93,
++ 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28,
++ 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99,
++ 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93,
++ 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36,
++ 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x9f, 0x52, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47,
++ 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30,
++ 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c,
++ 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36,
++ 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48,
++ 0x47, 0x9f, 0x48, 0x48, 0x48, 0xa0, 0xa1, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36,
++ 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f,
++ 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36,
++ 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48,
++ 0xa3, 0xa4, 0x48, 0x48, 0x9f, 0xa5, 0xa6, 0x9f,
++ 0x48, 0x48, 0x48, 0xa2, 0xa7, 0x47, 0x48, 0x48,
++ 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23,
++ 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d,
++ 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25,
++ 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0xa8, 0xa1, 0x48, 0x48, 0x9f, 0xa9, 0xa6, 0x9f,
++ 0x48, 0x48, 0xaa, 0xa1, 0xa5, 0x9f, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30,
++ 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32,
++ 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a,
++ 0x36, 0x24, 0x4f, 0x48, 0x52, 0x52, 0x48, 0x48,
++ 0xab, 0xac, 0xa0, 0x48, 0xad, 0xa6, 0xa6, 0x9f,
++ 0x48, 0xa2, 0xa9, 0xa6, 0xa2, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30,
++ 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21,
++ 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25,
++ 0x36, 0x3a, 0x48, 0x48, 0xae, 0xaf, 0x48, 0x48,
++ 0xad, 0xac, 0xa1, 0x9f, 0xa2, 0xa9, 0xa9, 0xa2,
++ 0x48, 0xab, 0x78, 0xa7, 0x48, 0x48, 0x48, 0x48,
++ 0x9f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21,
++ 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36,
++ 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21,
++ 0x23, 0x43, 0x48, 0x48, 0xb0, 0xb1, 0xb2, 0x9f,
++ 0x48, 0xb3, 0xa5, 0xb3, 0xab, 0xa9, 0xa9, 0xb3,
++ 0xb4, 0xa9, 0xb5, 0xb0, 0x48, 0x48, 0xa0, 0xa5,
++ 0xa1, 0xad, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36,
++ 0x2e, 0x9b, 0x48, 0x48, 0x48, 0xb6, 0xb7, 0xa4,
++ 0xa2, 0xa7, 0xb5, 0x78, 0x6f, 0x6f, 0x6e, 0x6f,
++ 0xa9, 0xb5, 0xab, 0x48, 0x9f, 0xab, 0xa9, 0xa1,
++ 0xaa, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36,
++ 0x54, 0x48, 0x48, 0x48, 0x48, 0xa2, 0xa8, 0xa1,
++ 0xa5, 0xa6, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x6f, 0x78, 0xa5, 0xa0, 0xa0, 0x78, 0xa6, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36,
++ 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21,
++ 0x43, 0x48, 0x4b, 0xa2, 0x9f, 0x48, 0xa2, 0xa1,
++ 0xb8, 0x6e, 0x6e, 0xb5, 0x78, 0x6f, 0x78, 0x78,
++ 0x6e, 0x6f, 0x78, 0xb5, 0xa6, 0xa1, 0xa0, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21,
++ 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25,
++ 0x52, 0x48, 0xa3, 0xb1, 0xb6, 0xb3, 0xaa, 0xac,
++ 0x68, 0x68, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x78, 0x6f, 0x6f, 0xb5, 0xa6, 0xb4, 0x48, 0x9f,
++ 0xb4, 0xb4, 0xa2, 0x9f, 0x48, 0x48, 0x4f, 0x21,
++ 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a,
++ 0x47, 0x48, 0xa2, 0xb6, 0xaf, 0xb9, 0xba, 0x68,
++ 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x78,
++ 0x6f, 0x6f, 0xa6, 0x6f, 0xb5, 0xa0, 0xaa, 0xa6,
++ 0xa6, 0xa9, 0xb2, 0xb3, 0x48, 0x48, 0x4c, 0x22,
++ 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39,
++ 0x9b, 0x48, 0x48, 0x48, 0xb0, 0xb0, 0xba, 0xb8,
++ 0x68, 0x68, 0x69, 0x78, 0x6f, 0xb5, 0x6f, 0xb5,
++ 0x78, 0x78, 0x78, 0x78, 0x78, 0xa5, 0xbb, 0xa9,
++ 0xa5, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23,
++ 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31,
++ 0x9b, 0x48, 0x48, 0x48, 0x48, 0x9f, 0xac, 0x68,
++ 0xbc, 0x6e, 0x6e, 0x6e, 0xb5, 0x6f, 0x6e, 0x6f,
++ 0x6f, 0x78, 0x78, 0xb5, 0xb5, 0xa5, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22,
++ 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d,
++ 0x9b, 0x48, 0x48, 0xb0, 0xaa, 0xb3, 0xbd, 0xb8,
++ 0xb8, 0x68, 0x6e, 0x6e, 0xb5, 0x6f, 0x78, 0x6e,
++ 0x78, 0x6f, 0x78, 0x78, 0xb5, 0xa9, 0xa2, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x24, 0x27, 0xbe, 0x24, 0x25, 0x28, 0x21, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25,
++ 0x39, 0x4d, 0xbf, 0x84, 0x81, 0x57, 0x21, 0x39,
++ 0x52, 0x48, 0x48, 0x62, 0xb1, 0xc0, 0xc1, 0xc1,
++ 0xb8, 0xb8, 0x68, 0xbc, 0x6e, 0x6e, 0x6e, 0x78,
++ 0x78, 0x78, 0x78, 0x6e, 0x78, 0xa9, 0xa0, 0xab,
++ 0xb3, 0xa2, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28,
++ 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30,
++ 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30,
++ 0x2d, 0xc2, 0x7a, 0xc3, 0xc4, 0xc4, 0x7f, 0x22,
++ 0x51, 0x52, 0x48, 0x48, 0xb0, 0xaa, 0xa8, 0xbd,
++ 0x68, 0xb8, 0xb8, 0x68, 0x68, 0x6e, 0x6e, 0x6f,
++ 0x6e, 0x6e, 0xb5, 0x6e, 0x78, 0xab, 0xab, 0xb5,
++ 0x78, 0xa6, 0xb3, 0xc5, 0xac, 0xac, 0xc6, 0x61,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32,
++ 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31,
++ 0x4d, 0x91, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0x5a,
++ 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0xb0, 0x64,
++ 0xc1, 0xb8, 0xb8, 0xb8, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6f, 0x71, 0x6f, 0x6f, 0xa6, 0xa0, 0x9f, 0xb4,
++ 0xb4, 0xa0, 0xa1, 0xb7, 0xc7, 0x69, 0x66, 0xc8,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25,
++ 0x83, 0xc9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a,
++ 0x60, 0x85, 0xca, 0xcb, 0xc4, 0xc4, 0xc4, 0x82,
++ 0x86, 0x36, 0x32, 0x3f, 0xa2, 0xa4, 0xa8, 0xa9,
++ 0xb8, 0xb8, 0xb8, 0xb8, 0x68, 0x6e, 0x6e, 0x6e,
++ 0x6e, 0x71, 0x6f, 0x71, 0xa6, 0xb4, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0xcc, 0xc3, 0xc7, 0xcd, 0xce,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57,
++ 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x23, 0x30, 0x31, 0xcf, 0x91, 0x7e, 0x90, 0x90,
++ 0x8b, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0x5d, 0xd0, 0x36, 0x24, 0xd1, 0xb1, 0xaf, 0xaa,
++ 0xba, 0xb8, 0x68, 0x68, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6e, 0x6f, 0x6e, 0x78, 0xa1, 0xa9, 0xa1, 0xb0,
++ 0x9f, 0x9b, 0x99, 0xcc, 0x64, 0x5c, 0x8b, 0xd0,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d,
++ 0x82, 0x5c, 0xd2, 0x2a, 0x23, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x24, 0x2b, 0xcf, 0x8b, 0x5b, 0x76, 0x5b, 0x5b,
++ 0x7b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc7, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48,
++ 0xa2, 0xa8, 0xb7, 0xc1, 0xb8, 0x68, 0x68, 0xbc,
++ 0x68, 0x6e, 0xb5, 0xb4, 0xb4, 0xab, 0xb5, 0xa1,
++ 0xb0, 0x4f, 0x3f, 0xd3, 0x7b, 0x7b, 0x85, 0x80,
++ 0xbe, 0x36, 0x36, 0x36, 0x21, 0xd4, 0x7e, 0x7b,
++ 0x64, 0x64, 0xd5, 0x35, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x31, 0xd6, 0x5b, 0x64, 0xc3, 0xc3, 0xcb,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x66, 0xd7, 0x36, 0x36, 0x36, 0x2c, 0x4b,
++ 0xd8, 0xd9, 0xb3, 0xa8, 0xbd, 0xbd, 0xbd, 0xbd,
++ 0xa9, 0xab, 0xb3, 0xa5, 0xa2, 0x9f, 0xa2, 0xa1,
++ 0x6a, 0x9a, 0x3f, 0xda, 0x76, 0x76, 0x7a, 0x63,
++ 0xdb, 0xdc, 0x86, 0xdc, 0xdd, 0x90, 0x5b, 0x64,
++ 0xc3, 0xc3, 0xde, 0x2d, 0x27, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc7, 0x83, 0xce, 0x36, 0x36, 0x36, 0x30,
++ 0xb1, 0xd9, 0x48, 0xa1, 0xb2, 0xb0, 0xb0, 0xb3,
++ 0xa2, 0x48, 0xa7, 0xbd, 0xa9, 0xa2, 0x48, 0x9f,
++ 0xaa, 0x9a, 0x3f, 0xb1, 0x5b, 0x7b, 0xdf, 0x85,
++ 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xc3, 0xc4,
++ 0xc4, 0xcb, 0x5d, 0xd5, 0x39, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe0, 0xdf, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x88, 0x36, 0x36, 0x36, 0x36,
++ 0x2d, 0x9b, 0x48, 0xb9, 0xaf, 0xa2, 0xa2, 0xb9,
++ 0xa8, 0x9f, 0x48, 0xa7, 0xb7, 0xd9, 0x48, 0x48,
++ 0x9b, 0x45, 0x3f, 0xe1, 0x6d, 0x7b, 0xca, 0xdf,
++ 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc3, 0xe2, 0x37, 0x35, 0x26, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2e, 0xe0, 0x7a, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x72, 0x73, 0x36, 0x36, 0x36,
++ 0x24, 0x52, 0x48, 0xa3, 0xaf, 0x9f, 0x48, 0xb6,
++ 0xaf, 0xa2, 0x48, 0x9f, 0xe3, 0xd8, 0x48, 0x48,
++ 0x48, 0x46, 0x42, 0xd6, 0x7a, 0x7b, 0x64, 0x7b,
++ 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xc3, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0x64, 0xe2, 0x4d, 0x2c, 0x27,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x8b, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc7, 0x89, 0xbe, 0x36, 0x36,
++ 0x32, 0x47, 0x48, 0x4f, 0xa0, 0x48, 0x48, 0xe3,
++ 0x92, 0x9f, 0x48, 0x9f, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xc3, 0xcb,
++ 0xc3, 0x64, 0x64, 0xc3, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x5d, 0xe5, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x85, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x57, 0x27, 0x4d,
++ 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x99, 0x34, 0xbe, 0xdb, 0x7a, 0x7b, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xe4,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe4, 0x85, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc7, 0x5f, 0x92, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44,
++ 0x35, 0x36, 0xce, 0xdd, 0x7a, 0x7b, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xc3, 0xe1,
++ 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x30, 0x2f, 0xd6, 0x8b, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x89, 0x45,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25,
++ 0x36, 0x36, 0x61, 0xdb, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0xdf, 0xe5,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xe6, 0x63, 0xdf, 0xc3, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x72, 0x81, 0xe7,
++ 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36,
++ 0x36, 0x36, 0xe8, 0x8f, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc3, 0xca, 0x8b, 0xcf, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x96, 0x75, 0xca, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0x81, 0xdb,
++ 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b,
++ 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x73, 0xdb, 0x7a, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x64, 0x76, 0x7a, 0x91, 0xd5, 0x31, 0x30,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x39, 0x97, 0x75, 0xdf, 0x7b, 0x64, 0xc3, 0xc3,
++ 0xcb, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x7b, 0x7a, 0xe9,
++ 0xea, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30,
++ 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xdd, 0x8b, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x64, 0x64,
++ 0x76, 0x85, 0xe0, 0xd5, 0x34, 0x2b, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xeb, 0x63, 0x7e, 0x7a, 0x6d, 0xdf, 0x5b,
++ 0x76, 0x7b, 0x64, 0x64, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x76, 0x85, 0xdb,
++ 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xec, 0xdd, 0x75, 0x76, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0xc3, 0x64, 0x76, 0xdf, 0x8b,
++ 0xd6, 0xd5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x31, 0xed, 0xeb, 0xdd, 0x74, 0x63, 0x90,
++ 0x7e, 0x75, 0x8b, 0x6d, 0xdf, 0x76, 0x64, 0xc3,
++ 0xcb, 0xcb, 0xcb, 0xcb, 0x64, 0x7a, 0x84, 0xee,
++ 0x79, 0xbe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xee, 0x63, 0x6d, 0x7b, 0x64,
++ 0xcb, 0xc3, 0x64, 0x7b, 0xdf, 0x75, 0x63, 0x96,
++ 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x27, 0x35, 0x2d, 0x41, 0xd5, 0xe7, 0x8f,
++ 0xdb, 0xdd, 0xe9, 0x74, 0x84, 0x90, 0x85, 0x6d,
++ 0x5b, 0x7b, 0x7b, 0xca, 0x6d, 0x90, 0xdb, 0xef,
++ 0xec, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30,
++ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36,
++ 0x36, 0x21, 0xd4, 0x80, 0xe9, 0x7e, 0x6d, 0x76,
++ 0xca, 0x76, 0x6d, 0x85, 0x63, 0xdb, 0xd5, 0x34,
++ 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f,
++ 0x41, 0xf0, 0xf1, 0x6c, 0x80, 0xee, 0xdb, 0x74,
++ 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xef, 0x79,
++ 0xe8, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d,
++ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38,
++ 0x4d, 0x37, 0xf2, 0xf3, 0x8f, 0x74, 0x63, 0x7e,
++ 0x75, 0x7e, 0x63, 0xe9, 0x88, 0xe6, 0x31, 0x2a,
++ 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30,
++ 0x33, 0x39, 0x2e, 0x51, 0x41, 0xd2, 0x6c, 0xf3,
++ 0x80, 0xee, 0xee, 0xee, 0xf4, 0xf3, 0xd7, 0xf5,
++ 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27,
++ 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a,
++ 0x2b, 0x34, 0xf6, 0xec, 0xf7, 0x8f, 0xdd, 0xe9,
++ 0xe9, 0xdd, 0xee, 0x6c, 0x41, 0x39, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22,
++ 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41,
++ 0xf8, 0xd7, 0x79, 0x79, 0x79, 0xec, 0xf9, 0x51,
++ 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22,
++ 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23,
++ 0x24, 0x2a, 0x31, 0xfa, 0xea, 0x79, 0xf3, 0x80,
++ 0xf7, 0xdc, 0xfb, 0x2f, 0x35, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b,
++ 0x31, 0x2f, 0xf6, 0xfa, 0xfa, 0x2f, 0x2e, 0x33,
++ 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x27, 0x35, 0x34, 0xfa, 0xfa, 0xfa,
++ 0xfc, 0xf6, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28,
++ 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35,
++ 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24,
++ 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++};
++
++unsigned char linux_logo16[1];
++
++#endif /* INCLUDE_LINUX_LOGO_DATA */
++
++#include <linux/linux_logo.h>
++
+--- linux/include/asm-nios2nommu/local.h
++++ linux/include/asm-nios2nommu/local.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_LOCAL_H
++#define __NIOS2NOMMU_LOCAL_H
++
++#include <asm-generic/local.h>
++
++#endif /* __NIOS2NOMMU_LOCAL_H */
+--- linux/include/asm-nios2nommu/mc146818rtc.h
++++ linux/include/asm-nios2nommu/mc146818rtc.h
+@@ -0,0 +1,29 @@
++/*
++ * Machine dependent access functions for RTC registers.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MC146818RTC_H
++#define _NIOS2_MC146818RTC_H
++
++/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
++
++#endif /* _NIOS2_MC146818RTC_H */
+--- linux/include/asm-nios2nommu/mman.h
++++ linux/include/asm-nios2nommu/mman.h
+@@ -0,0 +1,68 @@
++/*
++ * Copied from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_MMAN_H__
++#define __NIOS2_MMAN_H__
++
++#define PROT_READ 0x1 /* page can be read */
++#define PROT_WRITE 0x2 /* page can be written */
++#define PROT_EXEC 0x4 /* page can be executed */
++#define PROT_SEM 0x8 /* page may be used for atomic ops */
++#define PROT_NONE 0x0 /* page can not be accessed */
++#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
++#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
++
++#define MAP_SHARED 0x01 /* Share changes */
++#define MAP_PRIVATE 0x02 /* Changes are private */
++#define MAP_TYPE 0x0f /* Mask for type of mapping */
++#define MAP_FIXED 0x10 /* Interpret addr exactly */
++#define MAP_ANONYMOUS 0x20 /* don't use a file */
++
++#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
++#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
++#define MAP_LOCKED 0x2000 /* pages are locked */
++#define MAP_NORESERVE 0x4000 /* don't check for reservations */
++#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++#define MAP_NONBLOCK 0x10000 /* do not block on IO */
++
++#define MS_ASYNC 1 /* sync memory asynchronously */
++#define MS_INVALIDATE 2 /* invalidate the caches */
++#define MS_SYNC 4 /* synchronous memory sync */
++
++#define MCL_CURRENT 1 /* lock all current mappings */
++#define MCL_FUTURE 2 /* lock all future mappings */
++
++#define MADV_NORMAL 0x0 /* default page-in behavior */
++#define MADV_RANDOM 0x1 /* page-in minimum required */
++#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
++#define MADV_WILLNEED 0x3 /* pre-fault pages */
++#define MADV_DONTNEED 0x4 /* discard these pages */
++
++/* compatibility flags */
++#define MAP_ANON MAP_ANONYMOUS
++#define MAP_FILE 0
++
++#endif /* __NIOS2_MMAN_H__ */
++
+--- linux/include/asm-nios2nommu/mmu_context.h
++++ linux/include/asm-nios2nommu/mmu_context.h
+@@ -0,0 +1,58 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_CONTEXT_H
++#define __NIOS2NOMMU_MMU_CONTEXT_H
++
++#include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++}
++
++extern inline int
++init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++ // mm->context = virt_to_phys(mm->pgd);
++ return(0);
++}
++
++#define destroy_context(mm) do { } while(0)
++
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
++{
++}
++
++#define deactivate_mm(tsk,mm) do { } while (0)
++
++extern inline void activate_mm(struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++}
++
++#endif
+--- linux/include/asm-nios2nommu/mmu.h
++++ linux/include/asm-nios2nommu/mmu.h
+@@ -0,0 +1,36 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_H
++#define __NIOS2NOMMU_MMU_H
++
++/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
++
++typedef struct {
++ struct vm_list_struct *vmlist;
++ unsigned long end_brk;
++} mm_context_t;
++
++#endif /* __NIOS2NOMMU_MMU_H */
+--- linux/include/asm-nios2nommu/module.h
++++ linux/include/asm-nios2nommu/module.h
+@@ -0,0 +1,36 @@
++#ifndef _NIOS2_MODULE_H
++#define _NIOS2_MODULE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/module.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct mod_arch_specific
++{
++};
++
++#define Elf_Shdr Elf32_Shdr
++#define Elf_Sym Elf32_Sym
++#define Elf_Ehdr Elf32_Ehdr
++
++#endif /* _NIOS_MODULE_H */
+--- linux/include/asm-nios2nommu/msgbuf.h
++++ linux/include/asm-nios2nommu/msgbuf.h
+@@ -0,0 +1,56 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MSGBUF_H
++#define _NIOS2_MSGBUF_H
++
++/*
++ * The msqid64_ds structure for nios2 architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct msqid64_ds {
++ struct ipc64_perm msg_perm;
++ __kernel_time_t msg_stime; /* last msgsnd time */
++ unsigned long __unused1;
++ __kernel_time_t msg_rtime; /* last msgrcv time */
++ unsigned long __unused2;
++ __kernel_time_t msg_ctime; /* last change time */
++ unsigned long __unused3;
++ unsigned long msg_cbytes; /* current number of bytes on queue */
++ unsigned long msg_qnum; /* number of messages in queue */
++ unsigned long msg_qbytes; /* max number of bytes on queue */
++ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
++ __kernel_pid_t msg_lrpid; /* last receive pid */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#endif /* _NIOS2_MSGBUF_H */
++
+--- linux/include/asm-nios2nommu/namei.h
++++ linux/include/asm-nios2nommu/namei.h
+@@ -0,0 +1,36 @@
++/*
++ * linux/include/asm-nios/namei.h
++ * Moved from m68k version
++ * Included from linux/fs/namei.c
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_NAMEI_H
++#define __NIOS2_NAMEI_H
++
++/* This dummy routine maybe changed to something useful
++ * for /usr/gnemul/ emulation stuff.
++ * Look at asm-sparc/namei.h for details.
++ */
++
++#define __emul_prefix() NULL
++
++#endif
+--- linux/include/asm-nios2nommu/ndma.h
++++ linux/include/asm-nios2nommu/ndma.h
+@@ -0,0 +1,64 @@
++#ifndef __NDMA_H__
++ #define __NDMA_H__
++
++ #ifndef __ASSEMBLY__
++
++// DMA Registers
++typedef volatile struct
++{
++ int np_dmastatus; // status register
++ int np_dmareadaddress; // read address
++ int np_dmawriteaddress; // write address
++ int np_dmalength; // length in bytes
++ int np_dmareserved1; // reserved
++ int np_dmareserved2; // reserved
++ int np_dmacontrol; // control register
++ int np_dmareserved3; // control register alternate
++} np_dma;
++
++// DMA Register Bits
++enum
++{
++ np_dmacontrol_byte_bit = 0, // Byte transaction
++ np_dmacontrol_hw_bit = 1, // Half-word transaction
++ np_dmacontrol_word_bit = 2, // Word transaction
++ np_dmacontrol_go_bit = 3, // enable execution
++ np_dmacontrol_i_en_bit = 4, // enable interrupt
++ np_dmacontrol_reen_bit = 5, // Enable read end-of-packet
++ np_dmacontrol_ween_bit = 6, // Enable write end-of-packet
++ np_dmacontrol_leen_bit = 7, // Enable length=0 transaction end
++ np_dmacontrol_rcon_bit = 8, // Read from a fixed address
++ np_dmacontrol_wcon_bit = 9, // Write to a fixed address
++ np_dmacontrol_doubleword_bit = 10, // Double-word transaction
++ np_dmacontrol_quadword_bit = 11, // Quad-word transaction
++
++ np_dmastatus_done_bit = 0, // 1 when done. Status write clears.
++ np_dmastatus_busy_bit = 1, // 1 when busy.
++ np_dmastatus_reop_bit = 2, // read-eop received
++ np_dmastatus_weop_bit = 3, // write-eop received
++ np_dmastatus_len_bit = 4, // requested length transacted
++
++ np_dmacontrol_byte_mask = (1 << 0), // Byte transaction
++ np_dmacontrol_hw_mask = (1 << 1), // Half-word transaction
++ np_dmacontrol_word_mask = (1 << 2), // Word transaction
++ np_dmacontrol_go_mask = (1 << 3), // enable execution
++ np_dmacontrol_i_en_mask = (1 << 4), // enable interrupt
++ np_dmacontrol_reen_mask = (1 << 5), // Enable read end-of-packet
++ np_dmacontrol_ween_mask = (1 << 6), // Enable write end-of-packet
++ np_dmacontrol_leen_mask = (1 << 7), // Enable length=0 transaction end
++ np_dmacontrol_rcon_mask = (1 << 8), // Read from a fixed address
++ np_dmacontrol_wcon_mask = (1 << 9), // Write to a fixed address
++ np_dmacontrol_doubleword_mask = (1 << 10), // Double-word transaction
++ np_dmacontrol_quadword_mask = (1 << 11), // Quad-word transaction
++
++ np_dmastatus_done_mask = (1 << 0), // 1 when done. Status write clears.
++ np_dmastatus_busy_mask = (1 << 1), // 1 when busy.
++ np_dmastatus_reop_mask = (1 << 2), // read-eop received
++ np_dmastatus_weop_mask = (1 << 3), // write-eop received
++ np_dmastatus_len_mask = (1 << 4), // requested length transacted
++};
++
++ #endif /* __ASSEMBLY__ */
++
++#endif
++/* End of File */
+--- linux/include/asm-nios2nommu/nios.h
++++ linux/include/asm-nios2nommu/nios.h
+@@ -0,0 +1,7 @@
++#ifndef __NIOS_H__
++#define __NIOS_H__
++
++#include "nios2_system.h"
++
++#endif
++
+--- linux/include/asm-nios2nommu/page.h
++++ linux/include/asm-nios2nommu/page.h
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_PAGE_H
++#define _NIOS2_PAGE_H
++
++/* copied from m68knommu arch */
++// #include <linux/config.h>
++
++/* PAGE_SHIFT determines the page size */
++
++#define PAGE_SHIFT (12)
++#define PAGE_SIZE (1UL << PAGE_SHIFT)
++#define PAGE_MASK (~(PAGE_SIZE-1))
++
++#ifdef __KERNEL__
++
++#include <asm/setup.h>
++
++#if PAGE_SHIFT < 13
++#define THREAD_SIZE (8192)
++#else
++#define THREAD_SIZE PAGE_SIZE
++#endif
++
++#ifndef __ASSEMBLY__
++
++#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
++#define free_user_page(page, addr) free_page(addr)
++
++#define clear_page(page) memset((page), 0, PAGE_SIZE)
++#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
++
++#define clear_user_page(page, vaddr, pg) clear_page(page)
++#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
++
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef struct { unsigned long pte; } pte_t;
++typedef struct { unsigned long pmd[16]; } pmd_t;
++typedef struct { unsigned long pgd; } pgd_t;
++typedef struct { unsigned long pgprot; } pgprot_t;
++
++#define pte_val(x) ((x).pte)
++#define pmd_val(x) ((&x)->pmd[0])
++#define pgd_val(x) ((x).pgd)
++#define pgprot_val(x) ((x).pgprot)
++
++#define __pte(x) ((pte_t) { (x) } )
++#define __pmd(x) ((pmd_t) { (x) } )
++#define __pgd(x) ((pgd_t) { (x) } )
++#define __pgprot(x) ((pgprot_t) { (x) } )
++
++/* to align the pointer to the (next) page boundary */
++#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
++
++/* Pure 2^n version of get_order */
++extern __inline__ int get_order(unsigned long size)
++{
++ int order;
++
++ size = (size-1) >> (PAGE_SHIFT-1);
++ order = -1;
++ do {
++ size >>= 1;
++ order++;
++ } while (size);
++ return order;
++}
++
++extern unsigned long memory_start;
++extern unsigned long memory_end;
++
++#endif /* !__ASSEMBLY__ */
++#include <asm/nios.h>
++#define PAGE_OFFSET ((int)(nasys_program_mem))
++
++#ifndef __ASSEMBLY__
++
++#define __pa(vaddr) virt_to_phys((void *)vaddr)
++#define __va(paddr) phys_to_virt((unsigned long)paddr)
++
++#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
++
++#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
++#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
++
++#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
++#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
++#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
++
++#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
++#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
++
++#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
++ ((void *)(kaddr) < (void *)memory_end))
++
++#ifdef CONFIG_NO_KERNEL_MSG
++#define BUG_PRINT()
++#else
++#define BUG_PRINT() printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__)
++#endif
++
++#ifdef na_cpu_oci_core
++#define BUG_PANIC() asm volatile ("break") /* drop to debugger */
++#else
++// #define BUG_PANIC() while(1)
++#define BUG_PANIC() panic("BUG!")
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_PAGE_H */
+--- linux/include/asm-nios2nommu/param.h
++++ linux/include/asm-nios2nommu/param.h
+@@ -0,0 +1,49 @@
++#ifndef _NIOS_PARAM_H
++#define _NIOS_PARAM_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/param.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifndef HZ
++#define HZ 100
++#endif
++
++#ifdef __KERNEL__
++#define USER_HZ HZ
++#define CLOCKS_PER_SEC (USER_HZ)
++#endif
++
++#define EXEC_PAGESIZE 4096
++
++#ifndef NGROUPS
++#define NGROUPS 32
++#endif
++
++#ifndef NOGROUP
++#define NOGROUP (-1)
++#endif
++
++#define MAXHOSTNAMELEN 64 /* max length of hostname */
++
++#endif
+--- linux/include/asm-nios2nommu/pci.h
++++ linux/include/asm-nios2nommu/pci.h
+@@ -0,0 +1,75 @@
++#ifndef _ASM_NIOS2NOMMU_PCI_H
++#define _ASM_NIOS2NOMMU_PCI_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pci.h
++ *
++ * Derived from asm-m68k/pci_m68k.h
++ * - m68k specific PCI declarations, by Wout Klaren.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/scatterlist.h>
++
++struct pci_ops;
++
++/*
++ * Structure with hardware dependent information and functions of the
++ * PCI bus.
++ */
++
++struct pci_bus_info
++{
++ /*
++ * Resources of the PCI bus.
++ */
++
++ struct resource mem_space;
++ struct resource io_space;
++
++ /*
++ * System dependent functions.
++ */
++
++ struct pci_ops *m68k_pci_ops;
++
++ void (*fixup)(int pci_modify);
++ void (*conf_device)(struct pci_dev *dev);
++};
++
++#define pcibios_assign_all_busses() 0
++
++extern inline void pcibios_set_master(struct pci_dev *dev)
++{
++ /* No special bus mastering setup handling */
++}
++
++extern inline void pcibios_penalize_isa_irq(int irq)
++{
++ /* We don't do dynamic PCI IRQ allocation */
++}
++
++/* The PCI address space does equal the physical memory
++ * address space. The networking and block device layers use
++ * this boolean for bounce buffer decisions.
++ */
++#define PCI_DMA_BUS_IS_PHYS (1)
++
++#endif /* _ASM_NIOS2NOMMU_PCI_H */
+--- linux/include/asm-nios2nommu/percpu.h
++++ linux/include/asm-nios2nommu/percpu.h
+@@ -0,0 +1,30 @@
++#ifndef __ARCH_NIOS2NOMMU_PERCPU__
++#define __ARCH_NIOS2NOMMU_PERCPU__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/percpu.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/percpu.h>
++
++#endif /* __ARCH_NIOS2NOMMU_PERCPU__ */
+--- linux/include/asm-nios2nommu/pgalloc.h
++++ linux/include/asm-nios2nommu/pgalloc.h
+@@ -0,0 +1,32 @@
++#ifndef _NIOS2NOMMU_PGALLOC_H
++#define _NIOS2NOMMU_PGALLOC_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgalloc.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/setup.h>
++
++#define check_pgt_cache() do { } while (0)
++
++#endif /* _NIOS2NOMMU_PGALLOC_H */
+--- linux/include/asm-nios2nommu/pgtable.h
++++ linux/include/asm-nios2nommu/pgtable.h
+@@ -0,0 +1,104 @@
++#ifndef _NIOS_PGTABLE_H
++#define _NIOS_PGTABLE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgtable.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm-generic/4level-fixup.h>
++
++//vic - this bit copied from m68knommu version
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/io.h>
++
++typedef pte_t *pte_addr_t;
++
++#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
++#define pgd_none(pgd) (0)
++#define pgd_bad(pgd) (0)
++#define pgd_clear(pgdp)
++#define kern_addr_valid(addr) (1)
++#define pmd_offset(a, b) ((void *)0)
++
++#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
++//vic - this bit copied from m68knommu version
++
++extern void paging_init(void);
++#define swapper_pg_dir ((pgd_t *) 0)
++
++#define __swp_type(x) (0)
++#define __swp_offset(x) (0)
++#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
++#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
++#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
++
++static inline int pte_file(pte_t pte) { return 0; }
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++#define ZERO_PAGE(vaddr) (virt_to_page(0))
++
++extern unsigned int kobjsize(const void *objp);
++extern int is_in_rom(unsigned long);
++
++/*
++ * No page table caches to initialise
++ */
++#define pgtable_cache_init() do { } while (0)
++#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
++ remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
++
++extern inline void flush_cache_mm(struct mm_struct *mm)
++{
++}
++
++extern inline void flush_cache_range(struct mm_struct *mm,
++ unsigned long start,
++ unsigned long end)
++{
++}
++
++/* Push the page at kernel virtual address and clear the icache */
++extern inline void flush_page_to_ram (unsigned long address)
++{
++}
++
++/* Push n pages at kernel virtual address and clear the icache */
++extern inline void flush_pages_to_ram (unsigned long address, int n)
++{
++}
++
++/*
++ * All 32bit addresses are effectively valid for vmalloc...
++ * Sort of meaningless for non-VM targets.
++ */
++#define VMALLOC_START 0
++#define VMALLOC_END 0xffffffff
++
++#endif /* _NIOS_PGTABLE_H */
+--- linux/include/asm-nios2nommu/pio_struct.h
++++ linux/include/asm-nios2nommu/pio_struct.h
+@@ -0,0 +1,14 @@
++// PIO Peripheral
++
++// PIO Registers
++typedef volatile struct
++ {
++ int np_piodata; // read/write, up to 32 bits
++ int np_piodirection; // write/readable, up to 32 bits, 1->output bit
++ int np_piointerruptmask; // write/readable, up to 32 bits, 1->enable interrupt
++ int np_pioedgecapture; // read, up to 32 bits, cleared by any write
++ } np_pio;
++
++// PIO Routines
++void nr_pio_showhex(int value); // shows low byte on pio named na_seven_seg_pio
++
+--- linux/include/asm-nios2nommu/poll.h
++++ linux/include/asm-nios2nommu/poll.h
+@@ -0,0 +1,46 @@
++#ifndef __NIOS2_POLL_H
++#define __NIOS2_POLL_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/poll.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define POLLIN 1
++#define POLLPRI 2
++#define POLLOUT 4
++#define POLLERR 8
++#define POLLHUP 16
++#define POLLNVAL 32
++#define POLLRDNORM 64
++#define POLLWRNORM POLLOUT
++#define POLLRDBAND 128
++#define POLLWRBAND 256
++#define POLLMSG 0x0400
++
++struct pollfd {
++ int fd;
++ short events;
++ short revents;
++};
++
++#endif
+--- linux/include/asm-nios2nommu/posix_types.h
++++ linux/include/asm-nios2nommu/posix_types.h
+@@ -0,0 +1,89 @@
++#ifndef __ARCH_NIOS2_POSIX_TYPES_H
++#define __ARCH_NIOS2_POSIX_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/posix_types.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned short __kernel_uid_t;
++typedef unsigned short __kernel_gid_t;
++typedef unsigned int __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__KERNEL__) || defined(__USE_ALL)
++ int val[2];
++#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++ int __val[2];
++#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++} __kernel_fsid_t;
++
++#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
++
++#undef __FD_SET
++#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
++
++#undef __FD_CLR
++#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
++
++#undef __FD_ISSET
++#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
++
++#undef __FD_ZERO
++#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
++
++#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
++
++#endif
+--- linux/include/asm-nios2nommu/preem_latency.h
++++ linux/include/asm-nios2nommu/preem_latency.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_PREEM_LATENCY_H
++#define _ASM_PREEM_LATENCY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/preem_latency.h
++ *
++ * timing support for preempt-stats patch
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++#define readclock(low) \
++do {\
++ *(volatile unsigned long *)na_Counter_64_bit=1; \
++ low=*(volatile unsigned long *)na_Counter_64_bit; \
++} while (0)
++#define readclock_init()
++
++#endif /* _ASM_PREEM_LATENCY_H */
+--- linux/include/asm-nios2nommu/processor.h
++++ linux/include/asm-nios2nommu/processor.h
+@@ -0,0 +1,148 @@
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/processor.h
++ *
++ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2001 Ken Hill (khill@microtronix.com)
++ * Vic Phillips (vic@microtronix.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * hacked from:
++ * include/asm-sparc/processor.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ * Nov/02/2003 dgt Fix task_size
++ *
++ ---------------------------------------------------------------------*/
++
++#ifndef __ASM_NIOS_PROCESSOR_H
++#define __ASM_NIOS_PROCESSOR_H
++
++#define NIOS2_FLAG_KTHREAD 0x00000001 /* task is a kernel thread */
++#define NIOS2_FLAG_COPROC 0x00000002 /* Thread used coprocess */
++#define NIOS2_FLAG_DEBUG 0x00000004 /* task is being debugged */
++
++#define NIOS2_OP_NOP 0x1883a
++#define NIOS2_OP_BREAK 0x3da03a
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l;})
++
++#include <linux/a.out.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/signal.h>
++#include <asm/segment.h>
++#include <asm/current.h>
++#include <asm/system.h> /* for get_hi_limit */
++
++/*
++ * Bus types
++ */
++#define EISA_bus 0
++#define EISA_bus__is_a_macro /* for versions in ksyms.c */
++#define MCA_bus 0
++#define MCA_bus__is_a_macro /* for versions in ksyms.c */
++
++/*
++ * The nios has no problems with write protection
++ */
++#define wp_works_ok 1
++#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
++
++/* Whee, this is STACK_TOP and the lowest kernel address too... */
++#if 0
++#define KERNBASE 0x00000000 /* First address the kernel will eventually be */
++#define TASK_SIZE (KERNBASE)
++#define MAX_USER_ADDR TASK_SIZE
++#define MMAP_SEARCH_START (TASK_SIZE/3)
++#endif
++
++#define TASK_SIZE ((unsigned int) nasys_program_mem_end) //...this is better...
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
++ * space during mmap's. We won't be using it
++ */
++#define TASK_UNMAPPED_BASE 0
++
++/* The Nios processor specific thread struct. */
++struct thread_struct {
++ struct pt_regs *kregs;
++
++ /* For signal handling */
++ unsigned long sig_address;
++ unsigned long sig_desc;
++
++ /* Context switch saved kernel state. */
++ unsigned long ksp;
++ unsigned long kpsr;
++ unsigned long kesr;
++
++ /* Flags are defined below */
++
++ unsigned long flags;
++ int current_ds;
++ struct exec core_exec; /* just what it says. */
++};
++
++#define INIT_MMAP { &init_mm, (0), (0), \
++ __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC }
++
++#define INIT_THREAD { \
++ .kregs = 0, \
++ .sig_address = 0, \
++ .sig_desc = 0, \
++ .ksp = 0, \
++ .kpsr = 0, \
++ .kesr = PS_S, \
++ .flags = NIOS2_FLAG_KTHREAD, \
++ .current_ds = __KERNEL_DS, \
++ .core_exec = INIT_EXEC \
++}
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++extern unsigned long thread_saved_pc(struct task_struct *t);
++
++extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++#define prepare_to_copy(tsk) do { } while (0)
++
++extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define KSTK_EIP(tsk) ((tsk)->thread.kregs->ea)
++#define KSTK_ESP(tsk) ((tsk)->thread.kregs->sp)
++
++#ifdef __KERNEL__
++/* Allocation and freeing of basic task resources. */
++
++//;dgt2;#define alloc_task_struct() ((struct task_struct *) xx..see..linux..fork..xx __get_free_pages(GFP_KERNEL,1))
++//;dgt2;#define get_task_struct(tsk) xx..see..linux..sched.h...atomic_inc(&mem_map[MAP_NR(tsk)].count)
++
++#endif
++
++#define cpu_relax() do { } while (0)
++#endif /* __ASSEMBLY__ */
++#endif /* __ASM_NIOS_PROCESSOR_H */
+--- linux/include/asm-nios2nommu/ptrace.h
++++ linux/include/asm-nios2nommu/ptrace.h
+@@ -0,0 +1,141 @@
++/*
++ * Taken from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_PTRACE_H
++#define _NIOS2NOMMU_PTRACE_H
++
++#ifndef __ASSEMBLY__
++
++#define PTR_R0 0
++#define PTR_R1 1
++#define PTR_R2 2
++#define PTR_R3 3
++#define PTR_R4 4
++#define PTR_R5 5
++#define PTR_R6 6
++#define PTR_R7 7
++#define PTR_R8 8
++#define PTR_R9 9
++#define PTR_R10 10
++#define PTR_R11 11
++#define PTR_R12 12
++#define PTR_R13 13
++#define PTR_R14 14
++#define PTR_R15 15
++#define PTR_R16 16
++#define PTR_R17 17
++#define PTR_R18 18
++#define PTR_R19 19
++#define PTR_R20 20
++#define PTR_R21 21
++#define PTR_R22 22
++#define PTR_R23 23
++#define PTR_R24 24
++#define PTR_R25 25
++#define PTR_GP 26
++#define PTR_SP 27
++#define PTR_FP 28
++#define PTR_EA 29
++#define PTR_BA 30
++#define PTR_RA 31
++#define PTR_STATUS 32
++#define PTR_ESTATUS 33
++#define PTR_BSTATUS 34
++#define PTR_IENABLE 35
++#define PTR_IPENDING 36
++
++/* this struct defines the way the registers are stored on the
++ stack during a system call.
++
++ There is a fake_regs in setup.c that has to match pt_regs.*/
++
++struct pt_regs {
++ unsigned long r8;
++ unsigned long r9;
++ unsigned long r10;
++ unsigned long r11;
++ unsigned long r12;
++ unsigned long r13;
++ unsigned long r14;
++ unsigned long r15;
++ unsigned long r1;
++ unsigned long r2;
++ unsigned long r3;
++ unsigned long r4;
++ unsigned long r5;
++ unsigned long r6;
++ unsigned long r7;
++ unsigned long orig_r2;
++ unsigned long ra;
++ unsigned long fp;
++ unsigned long sp;
++ unsigned long gp;
++ unsigned long estatus;
++ unsigned long status_extension;
++ unsigned long ea;
++};
++
++
++/*
++ * This is the extended stack used by signal handlers and the context
++ * switcher: it's pushed after the normal "struct pt_regs".
++ */
++struct switch_stack {
++ unsigned long r16;
++ unsigned long r17;
++ unsigned long r18;
++ unsigned long r19;
++ unsigned long r20;
++ unsigned long r21;
++ unsigned long r22;
++ unsigned long r23;
++ unsigned long fp;
++ unsigned long gp;
++ unsigned long ra;
++};
++
++/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
++#define PTRACE_GETREGS 12
++#define PTRACE_SETREGS 13
++#ifdef CONFIG_FPU
++#define PTRACE_GETFPREGS 14
++#define PTRACE_SETFPREGS 15
++#endif
++
++#ifdef __KERNEL__
++
++#ifndef PS_S
++#define PS_S (0x00000001)
++#endif
++#ifndef PS_T
++#define PS_T (0x00000002)
++#endif
++
++#define user_mode(regs) (!((regs)->status_extension & PS_S))
++#define instruction_pointer(regs) ((regs)->ra)
++#define profile_pc(regs) instruction_pointer(regs)
++extern void show_regs(struct pt_regs *);
++
++#endif /* __KERNEL__ */
++#endif /* __ASSEMBLY__ */
++#endif /* _NIOS2NOMMU_PTRACE_H */
+--- linux/include/asm-nios2nommu/resource.h
++++ linux/include/asm-nios2nommu/resource.h
+@@ -0,0 +1,73 @@
++#ifndef _NIOS2NOMMU_RESOURCE_H
++#define _NIOS2NOMMU_RESOURCE_H
++
++/*--------------------------------------------------------------------
++ *
++ * Resource limits
++ *
++ * include/asm-nios2nommu/resource.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define RLIMIT_CPU 0 /* CPU time in ms */
++#define RLIMIT_FSIZE 1 /* Maximum filesize */
++#define RLIMIT_DATA 2 /* max data size */
++#define RLIMIT_STACK 3 /* max stack size */
++#define RLIMIT_CORE 4 /* max core file size */
++#define RLIMIT_RSS 5 /* max resident set size */
++#define RLIMIT_NPROC 6 /* max number of processes */
++#define RLIMIT_NOFILE 7 /* max number of open files */
++#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
++#define RLIMIT_AS 9 /* address space limit */
++#define RLIMIT_LOCKS 10 /* maximum file locks held */
++#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
++#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
++
++#define RLIM_NLIMITS 13
++
++/*
++ * SuS says limits have to be unsigned.
++ * Which makes a ton more sense anyway.
++ */
++#define RLIM_INFINITY (~0UL)
++
++#ifdef __KERNEL__
++
++#define INIT_RLIMITS \
++{ \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { _STK_LIM, RLIM_INFINITY }, \
++ { 0, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { 0, 0 }, \
++ { INR_OPEN, INR_OPEN }, \
++ { MLOCK_LIMIT, MLOCK_LIMIT }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { MAX_SIGPENDING, MAX_SIGPENDING }, \
++ { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
++}
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2NOMMU_RESOURCE_H */
+--- linux/include/asm-nios2nommu/rmap.h
++++ linux/include/asm-nios2nommu/rmap.h
+@@ -0,0 +1,2 @@
++/* Do not need anything here */
++
+--- linux/include/asm-nios2nommu/scatterlist.h
++++ linux/include/asm-nios2nommu/scatterlist.h
+@@ -0,0 +1,42 @@
++#ifndef _NIOS2NOMMU_SCATTERLIST_H
++#define _NIOS2NOMMU_SCATTERLIST_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/scatterlist.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <linux/mm.h>
++
++struct scatterlist {
++ struct page *page;
++ unsigned int offset;
++ dma_addr_t dma_address;
++ unsigned int length;
++};
++
++#define sg_address(sg) (page_address((sg)->page) + (sg)->offset
++#define sg_dma_address(sg) ((sg)->dma_address)
++#define sg_dma_len(sg) ((sg)->length)
++
++#define ISA_DMA_THRESHOLD (0xffffffff)
++
++#endif /* !(_NIOS2NOMMU_SCATTERLIST_H) */
+--- linux/include/asm-nios2nommu/sections.h
++++ linux/include/asm-nios2nommu/sections.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_SECTIONS_H
++#define _NIOS2NOMMU_SECTIONS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sections.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/sections.h>
++
++#endif /* _NIOS2NOMMU_SECTIONS_H */
+--- linux/include/asm-nios2nommu/segment.h
++++ linux/include/asm-nios2nommu/segment.h
+@@ -0,0 +1,75 @@
++#ifndef _NIOS2NOMMU_SEGMENT_H
++#define _NIOS2NOMMU_SEGMENT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/segment.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* define constants */
++/* Address spaces (FC0-FC2) */
++#define USER_DATA (1)
++#ifndef __USER_DS
++#define __USER_DS (USER_DATA)
++#endif
++#define USER_PROGRAM (2)
++#define SUPER_DATA (5)
++#ifndef __KERNEL_DS
++#define __KERNEL_DS (SUPER_DATA)
++#endif
++#define SUPER_PROGRAM (6)
++#define CPU_SPACE (7)
++
++#ifndef __ASSEMBLY__
++
++typedef struct {
++ unsigned long seg;
++} mm_segment_t;
++
++#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
++#define USER_DS MAKE_MM_SEG(__USER_DS)
++#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
++
++/*
++ * Get/set the SFC/DFC registers for MOVES instructions
++ */
++
++static inline mm_segment_t get_fs(void)
++{
++ return USER_DS;
++}
++
++static inline mm_segment_t get_ds(void)
++{
++ /* return the supervisor data space code */
++ return KERNEL_DS;
++}
++
++static inline void set_fs(mm_segment_t val)
++{
++}
++
++#define segment_eq(a,b) ((a).seg == (b).seg)
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _NIOS2NOMMU_SEGMENT_H */
+--- linux/include/asm-nios2nommu/semaphore.h
++++ linux/include/asm-nios2nommu/semaphore.h
+@@ -0,0 +1,155 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_H
++#define _NIOS2NOMMU_SEMAPHORE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * Interrupt-safe semaphores..
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define RW_LOCK_BIAS 0x01000000
++
++#ifndef __ASSEMBLY__
++
++#include <linux/linkage.h>
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++
++#include <asm/system.h>
++#include <asm/atomic.h>
++
++struct semaphore {
++ atomic_t count;
++ atomic_t waking;
++ wait_queue_head_t wait;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n) \
++{ \
++ .count = ATOMIC_INIT(n), \
++ .waking = ATOMIC_INIT(0), \
++ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
++}
++
++#define __MUTEX_INITIALIZER(name) \
++ __SEMAPHORE_INITIALIZER(name,1)
++
++#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
++ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
++
++#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
++#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
++
++extern inline void sema_init (struct semaphore *sem, int val)
++{
++ *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
++}
++
++static inline void init_MUTEX (struct semaphore *sem)
++{
++ sema_init(sem, 1);
++}
++
++static inline void init_MUTEX_LOCKED (struct semaphore *sem)
++{
++ sema_init(sem, 0);
++}
++
++asmlinkage void __down(struct semaphore * sem);
++asmlinkage int __down_interruptible(struct semaphore * sem);
++asmlinkage int __down_trylock(struct semaphore * sem);
++asmlinkage void __up(struct semaphore * sem);
++
++asmlinkage void __down_failed(void /* special register calling convention */);
++asmlinkage int __down_failed_interruptible(void /* params in registers */);
++asmlinkage int __down_failed_trylock(void /* params in registers */);
++asmlinkage void __up_wakeup(void /* special register calling convention */);
++
++extern spinlock_t semaphore_wake_lock;
++
++/*
++ * This is ugly, but we want the default case to fall through.
++ * "down_failed" is a special asm handler that calls the C
++ * routine that actually waits.
++ */
++extern inline void down(struct semaphore * sem)
++{
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if (atomic_dec_return(&sem->count) < 0)
++ __down(sem);
++ #endif
++}
++
++extern inline int down_interruptible(struct semaphore * sem)
++{
++ int ret = 0;
++
++
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if(atomic_dec_return(&sem->count) < 0)
++ ret = __down_interruptible(sem);
++ return ret;
++ #endif
++}
++
++extern inline int down_trylock(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ int ret = 0;
++
++ if (atomic_dec_return (&sem->count) < 0)
++ ret = __down_trylock(sem);
++ return ret;
++ #endif
++}
++
++/*
++ * Note! This is subtle. We jump to wake people up only if
++ * the semaphore was negative (== somebody was waiting on it).
++ * The default case (no contention) will result in NO
++ * jumps for both down() and up().
++ */
++extern inline void up(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "increment memory"....
++ #else
++ if (atomic_inc_return(&sem->count) <= 0)
++ __up(sem);
++ #endif
++}
++
++#endif /* __ASSEMBLY__ */
++
++#endif
+--- linux/include/asm-nios2nommu/semaphore-helper.h
++++ linux/include/asm-nios2nommu/semaphore-helper.h
+@@ -0,0 +1,101 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_HELPER_H
++#define _NIOS2NOMMU_SEMAPHORE_HELPER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * SMP- and interrupt-safe semaphores helper functions.
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++// #include <linux/config.h>
++
++/*
++ * These two _must_ execute atomically wrt each other.
++ */
++static inline void wake_one_more(struct semaphore * sem)
++{
++ atomic_inc(&sem->waking);
++}
++
++static inline int waking_non_zero(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_interruptible:
++ * 1 got the lock
++ * 0 go to sleep
++ * -EINTR interrupted
++ */
++static inline int waking_non_zero_interruptible(struct semaphore *sem,
++ struct task_struct *tsk)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ } else if (signal_pending(tsk)) {
++ atomic_inc(&sem->count);
++ ret = -EINTR;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_trylock:
++ * 1 failed to lock
++ * 0 got the lock
++ */
++static inline int waking_non_zero_trylock(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 1;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 0;
++ } else
++ atomic_inc(&sem->count);
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++#endif
+--- linux/include/asm-nios2nommu/sembuf.h
++++ linux/include/asm-nios2nommu/sembuf.h
+@@ -0,0 +1,48 @@
++#ifndef _NIOS_SEMBUF_H
++#define _NIOS_SEMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sembuf.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct semid64_ds {
++ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
++ __kernel_time_t sem_otime; /* last semop time */
++ unsigned long __unused1;
++ __kernel_time_t sem_ctime; /* last change time */
++ unsigned long __unused2;
++ unsigned long sem_nsems; /* no. of semaphores in array */
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SEMBUF_H */
+--- linux/include/asm-nios2nommu/setup.h
++++ linux/include/asm-nios2nommu/setup.h
+@@ -0,0 +1,31 @@
++/* Copied from i386 port.
++ * Just a place holder. We don't want to have to test x86 before
++ * we include stuff
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SETUP_H
++#define _NIOS2_SETUP_H
++
++#define COMMAND_LINE_SIZE 512
++
++#endif /* _NIOS2_SETUP_H */
+--- linux/include/asm-nios2nommu/shmbuf.h
++++ linux/include/asm-nios2nommu/shmbuf.h
+@@ -0,0 +1,64 @@
++#ifndef _NIOS_SHMBUF_H
++#define _NIOS_SHMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmbuf.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct shmid64_ds {
++ struct ipc64_perm shm_perm; /* operation perms */
++ size_t shm_segsz; /* size of segment (bytes) */
++ __kernel_time_t shm_atime; /* last attach time */
++ unsigned long __unused1;
++ __kernel_time_t shm_dtime; /* last detach time */
++ unsigned long __unused2;
++ __kernel_time_t shm_ctime; /* last change time */
++ unsigned long __unused3;
++ __kernel_pid_t shm_cpid; /* pid of creator */
++ __kernel_pid_t shm_lpid; /* pid of last operator */
++ unsigned long shm_nattch; /* no. of current attaches */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++struct shminfo64 {
++ unsigned long shmmax;
++ unsigned long shmmin;
++ unsigned long shmmni;
++ unsigned long shmseg;
++ unsigned long shmall;
++ unsigned long __unused1;
++ unsigned long __unused2;
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SHMBUF_H */
+--- linux/include/asm-nios2nommu/shmparam.h
++++ linux/include/asm-nios2nommu/shmparam.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS2NOMMU_SHMPARAM_H__
++#define __NIOS2NOMMU_SHMPARAM_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmparam.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
++
++#endif /* __NIOS2NOMMU_SHMPARAM_H__ */
+--- linux/include/asm-nios2nommu/sigcontext.h
++++ linux/include/asm-nios2nommu/sigcontext.h
+@@ -0,0 +1,35 @@
++/*
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_SIGCONTEXT_H
++#define _ASM_NIOS2NOMMU_SIGCONTEXT_H
++
++#include <asm/ptrace.h>
++
++struct sigcontext {
++ struct pt_regs regs;
++ unsigned long sc_mask; /* old sigmask */
++};
++
++#endif
+--- linux/include/asm-nios2nommu/siginfo.h
++++ linux/include/asm-nios2nommu/siginfo.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SIGINFO_H
++#define _NIOS2NOMMU_SIGINFO_H
++
++#include <asm-generic/siginfo.h>
++
++#endif
+--- linux/include/asm-nios2nommu/signal.h
++++ linux/include/asm-nios2nommu/signal.h
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SIGNAL_H
++#define _NIOS2_SIGNAL_H
++
++#include <linux/types.h>
++
++/* Avoid too many header ordering problems. */
++struct siginfo;
++
++#ifdef __KERNEL__
++/* Most things should be clean enough to redefine this at will, if care
++ is taken to make libc match. */
++
++#define _NSIG 64
++#define _NSIG_BPW 32
++#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
++
++typedef unsigned long old_sigset_t; /* at least 32 bits */
++
++typedef struct {
++ unsigned long sig[_NSIG_WORDS];
++} sigset_t;
++
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++#define NSIG 32
++typedef unsigned long sigset_t;
++
++#endif /* __KERNEL__ */
++
++#define SIGHUP 1
++#define SIGINT 2
++#define SIGQUIT 3
++#define SIGILL 4
++#define SIGTRAP 5
++#define SIGABRT 6
++#define SIGIOT 6
++#define SIGBUS 7
++#define SIGFPE 8
++#define SIGKILL 9
++#define SIGUSR1 10
++#define SIGSEGV 11
++#define SIGUSR2 12
++#define SIGPIPE 13
++#define SIGALRM 14
++#define SIGTERM 15
++#define SIGSTKFLT 16
++#define SIGCHLD 17
++#define SIGCONT 18
++#define SIGSTOP 19
++#define SIGTSTP 20
++#define SIGTTIN 21
++#define SIGTTOU 22
++#define SIGURG 23
++#define SIGXCPU 24
++#define SIGXFSZ 25
++#define SIGVTALRM 26
++#define SIGPROF 27
++#define SIGWINCH 28
++#define SIGIO 29
++#define SIGPOLL SIGIO
++/*
++#define SIGLOST 29
++*/
++#define SIGPWR 30
++#define SIGSYS 31
++#define SIGUNUSED 31
++
++/* These should not be considered constants from userland. */
++#define SIGRTMIN 32
++#define SIGRTMAX _NSIG-1
++
++/*
++ * SA_FLAGS values:
++ *
++ * SA_ONSTACK indicates that a registered stack_t will be used.
++ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
++ * SA_RESTART flag to get restarting signals (which were the default long ago)
++ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
++ * SA_RESETHAND clears the handler when the signal is delivered.
++ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
++ * SA_NODEFER prevents the current signal from being masked in the handler.
++ *
++ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
++ * Unix names RESETHAND and NODEFER respectively.
++ */
++#define SA_NOCLDSTOP 0x00000001
++#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
++#define SA_SIGINFO 0x00000004
++#define SA_ONSTACK 0x08000000
++#define SA_RESTART 0x10000000
++#define SA_NODEFER 0x40000000
++#define SA_RESETHAND 0x80000000
++
++#define SA_NOMASK SA_NODEFER
++#define SA_ONESHOT SA_RESETHAND
++#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
++
++#define SA_RESTORER 0x04000000
++
++/*
++ * sigaltstack controls
++ */
++#define SS_ONSTACK 1
++#define SS_DISABLE 2
++
++#define MINSIGSTKSZ 2048
++#define SIGSTKSZ 8192
++
++#ifdef __KERNEL__
++/*
++ * These values of sa_flags are used only by the kernel as part of the
++ * irq handling routines.
++ *
++ * SA_INTERRUPT is also used by the irq handling routines.
++ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
++ */
++#define SA_PROBE SA_ONESHOT
++#define SA_SAMPLE_RANDOM SA_RESTART
++#define SA_SHIRQ 0x04000000
++#endif
++
++#define SIG_BLOCK 0 /* for blocking signals */
++#define SIG_UNBLOCK 1 /* for unblocking signals */
++#define SIG_SETMASK 2 /* for setting the signal mask */
++
++/* Type of a signal handler. */
++typedef void (*__sighandler_t)(int);
++
++#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
++#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
++#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
++
++#ifdef __KERNEL__
++struct old_sigaction {
++ __sighandler_t sa_handler;
++ old_sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++struct sigaction {
++ __sighandler_t sa_handler;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++ sigset_t sa_mask; /* mask last for extensibility */
++};
++
++struct k_sigaction {
++ struct sigaction sa;
++};
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++struct sigaction {
++ union {
++ __sighandler_t _sa_handler;
++ void (*_sa_sigaction)(int, struct siginfo *, void *);
++ } _u;
++ sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++#define sa_handler _u._sa_handler
++#define sa_sigaction _u._sa_sigaction
++
++#endif /* __KERNEL__ */
++
++typedef struct sigaltstack {
++ void *ss_sp;
++ int ss_flags;
++ size_t ss_size;
++} stack_t;
++
++#ifdef __KERNEL__
++
++#include <asm/sigcontext.h>
++#undef __HAVE_ARCH_SIG_BITOPS
++
++#define ptrace_signal_deliver(regs, cookie) do { } while (0)
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_SIGNAL_H */
+--- linux/include/asm-nios2nommu/smp.h
++++ linux/include/asm-nios2nommu/smp.h
+@@ -0,0 +1,34 @@
++#ifndef __ASM_SMP_H
++#define __ASM_SMP_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/smp.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++// #include <linux/config.h>
++
++#ifdef CONFIG_SMP
++#error SMP not supported
++#endif
++
++#endif
+--- linux/include/asm-nios2nommu/socket.h
++++ linux/include/asm-nios2nommu/socket.h
+@@ -0,0 +1,74 @@
++#ifndef _ASM_SOCKET_H
++#define _ASM_SOCKET_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/socket.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/sockios.h>
++
++/* For setsockopt(2) */
++#define SOL_SOCKET 1
++
++#define SO_DEBUG 1
++#define SO_REUSEADDR 2
++#define SO_TYPE 3
++#define SO_ERROR 4
++#define SO_DONTROUTE 5
++#define SO_BROADCAST 6
++#define SO_SNDBUF 7
++#define SO_RCVBUF 8
++#define SO_KEEPALIVE 9
++#define SO_OOBINLINE 10
++#define SO_NO_CHECK 11
++#define SO_PRIORITY 12
++#define SO_LINGER 13
++#define SO_BSDCOMPAT 14
++/* To add :#define SO_REUSEPORT 15 */
++#define SO_PASSCRED 16
++#define SO_PEERCRED 17
++#define SO_RCVLOWAT 18
++#define SO_SNDLOWAT 19
++#define SO_RCVTIMEO 20
++#define SO_SNDTIMEO 21
++
++/* Security levels - as per NRL IPv6 - don't actually do anything */
++#define SO_SECURITY_AUTHENTICATION 22
++#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
++#define SO_SECURITY_ENCRYPTION_NETWORK 24
++
++#define SO_BINDTODEVICE 25
++
++/* Socket filtering */
++#define SO_ATTACH_FILTER 26
++#define SO_DETACH_FILTER 27
++
++#define SO_PEERNAME 28
++#define SO_TIMESTAMP 29
++#define SCM_TIMESTAMP SO_TIMESTAMP
++
++#define SO_ACCEPTCONN 30
++
++#define SO_PEERSEC 31 /* ;dgt2;tmp; */
++
++#endif /* _ASM_SOCKET_H */
+--- linux/include/asm-nios2nommu/sockios.h
++++ linux/include/asm-nios2nommu/sockios.h
+@@ -0,0 +1,38 @@
++#ifndef _ASM_NIOS_SOCKIOS_H
++#define _ASM_NIOS_SOCKIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sockios.h
++ *
++ * Socket-level I/O control calls.
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define FIOSETOWN 0x8901
++#define SIOCSPGRP 0x8902
++#define FIOGETOWN 0x8903
++#define SIOCGPGRP 0x8904
++#define SIOCATMARK 0x8905
++#define SIOCGSTAMP 0x8906 /* Get stamp */
++
++#endif /* !(_ASM_NIOS_SOCKIOS_H) */
++
+--- linux/include/asm-nios2nommu/spi.h
++++ linux/include/asm-nios2nommu/spi.h
+@@ -0,0 +1,92 @@
++#ifndef _ASM_SPI_H_
++#define _ASM_SPI_H_ 1
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spi.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++int register_NIOS_SPI( void );
++void unregister_NIOS_SPI( void );
++
++#if defined(MODULE)
++void cleanup_module( void );
++int init_module( void );
++#endif
++
++#if defined(__KERNEL__)
++int spi_reset ( void );
++#endif
++
++
++#define clockCS 0x01
++#define temperatureCS 0x02
++
++#define clock_read_base 0x00
++#define clock_write_base 0x80
++#define clock_read_control 0x0F
++#define clock_read_trickle 0x11
++
++#define clock_read_sec 0x00
++#define clock_read_min 0x01
++#define clock_read_hour 0x02
++#define clock_read_day 0x03
++#define clock_read_date 0x04
++#define clock_read_month 0x05
++#define clock_read_year 0x06
++
++#define clock_write_control 0x8F
++#define clock_write_trickle 0x91
++#define clock_write_sec 0x80
++#define clock_write_min 0x81
++#define clock_write_hour 0x82
++#define clock_write_day 0x83
++#define clock_write_date 0x84
++#define clock_write_month 0x85
++#define clock_write_year 0x86
++
++#define clock_write_ram_start 0xA0
++#define clock_write_ram_end 0x100
++#define clock_read_ram_start 0x20
++#define clock_read_ram_end 0x80
++
++
++#define clock_sec_def 0x11
++#define clock_min_def 0x59
++#define clock_hour_def 0x71
++#define clock_day_def 0x00
++#define clock_date_def 0x20
++#define clock_month_def 0x12
++#define clock_year_def 0x34
++
++#define temp_read_base 0x00
++#define temp_write_base 0x80
++#define temp_read_control 0x00
++#define temp_write_control 0x80
++#define temp_read_msb 0x02
++#define temp_read_lsb 0x01
++
++#define MAX_TEMP_VAR 10
++
++#endif /*_ASM_SPI_H_*/
+--- linux/include/asm-nios2nommu/spinlock.h
++++ linux/include/asm-nios2nommu/spinlock.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS_SPINLOCK_H
++#define __NIOS_SPINLOCK_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spinlock.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#error "Nios doesn't do SMP yet"
++
++#endif
+--- linux/include/asm-nios2nommu/spi_struct.h
++++ linux/include/asm-nios2nommu/spi_struct.h
+@@ -0,0 +1,57 @@
++// SPI Registers
++typedef volatile struct
++ {
++ int np_spirxdata; // Read-only, 1-16 bit
++ int np_spitxdata; // Write-only, same width as rxdata
++ int np_spistatus; // Read-only, 9-bit
++ int np_spicontrol; // Read/Write, 9-bit
++ int np_spireserved; // reserved
++ int np_spislaveselect; // Read/Write, 1-16 bit, master only
++ int np_spiendofpacket; // Read/write, same width as txdata, rxdata.
++ } np_spi;
++
++// SPI Status Register Bits
++enum
++ {
++ np_spistatus_eop_bit = 9,
++ np_spistatus_e_bit = 8,
++ np_spistatus_rrdy_bit = 7,
++ np_spistatus_trdy_bit = 6,
++ np_spistatus_tmt_bit = 5,
++ np_spistatus_toe_bit = 4,
++ np_spistatus_roe_bit = 3,
++
++ np_spistatus_eop_mask = (1 << 9),
++ np_spistatus_e_mask = (1 << 8),
++ np_spistatus_rrdy_mask = (1 << 7),
++ np_spistatus_trdy_mask = (1 << 6),
++ np_spistatus_tmt_mask = (1 << 5),
++ np_spistatus_toe_mask = (1 << 4),
++ np_spistatus_roe_mask = (1 << 3),
++ };
++
++// SPI Control Register Bits
++enum
++ {
++ np_spicontrol_sso_bit = 10,
++ np_spicontrol_ieop_bit = 9,
++ np_spicontrol_ie_bit = 8,
++ np_spicontrol_irrdy_bit = 7,
++ np_spicontrol_itrdy_bit = 6,
++ np_spicontrol_itoe_bit = 4,
++ np_spicontrol_iroe_bit = 3,
++
++ np_spicontrol_sso_mask = (1 << 10),
++ np_spicontrol_ieop_mask = (1 << 9),
++ np_spicontrol_ie_mask = (1 << 8),
++ np_spicontrol_irrdy_mask = (1 << 7),
++ np_spicontrol_itrdy_mask = (1 << 6),
++ np_spicontrol_itoe_mask = (1 << 4),
++ np_spicontrol_iroe_mask = (1 << 3),
++ };
++
++// SPI Routines.
++int nr_spi_rxchar(np_spi *spiBase);
++int nr_spi_txchar(int i, np_spi *spiBase);
++
++
+--- linux/include/asm-nios2nommu/statfs.h
++++ linux/include/asm-nios2nommu/statfs.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_STATFS_H
++#define _NIOS2NOMMU_STATFS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/statfs.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/statfs.h>
++
++#endif /* _NIOS2NOMMU_STATFS_H */
+--- linux/include/asm-nios2nommu/stat.h
++++ linux/include/asm-nios2nommu/stat.h
+@@ -0,0 +1,102 @@
++#ifndef _ASMNIOS2NOMMU_STAT_H
++#define _ASMNIOS2NOMMU_STAT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/stat.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct __old_kernel_stat {
++ unsigned short st_dev;
++ unsigned short st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned long st_size;
++ unsigned long st_atime;
++ unsigned long st_mtime;
++ unsigned long st_ctime;
++};
++
++struct stat {
++ unsigned short st_dev;
++ unsigned short __pad1;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned short __pad2;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long __unused1;
++ unsigned long st_mtime;
++ unsigned long __unused2;
++ unsigned long st_ctime;
++ unsigned long __unused3;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++/* This matches struct stat64 in glibc2.1, hence the absolutely
++ * insane amounts of padding around dev_t's.
++ */
++struct stat64 {
++ unsigned long long st_dev;
++ unsigned char __pad1[4];
++
++#define STAT64_HAS_BROKEN_ST_INO 1
++ unsigned long __st_ino;
++
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++ unsigned char __pad3[4];
++
++ long long st_size;
++ unsigned long st_blksize;
++
++ unsigned long __pad4; /* future possible st_blocks high bits */
++ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long long st_ino;
++};
++
++#endif
+--- linux/include/asm-nios2nommu/string.h
++++ linux/include/asm-nios2nommu/string.h
+@@ -0,0 +1,45 @@
++#ifndef __NIOS_STRING_H__
++#define __NIOS_STRING_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/string.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef __KERNEL__ /* only set these up for kernel code */
++
++#define __HAVE_ARCH_MEMMOVE
++void * memmove(void * d, const void * s, size_t count);
++#define __HAVE_ARCH_MEMCPY
++extern void * memcpy(void *d, const void *s, size_t count);
++#define __HAVE_ARCH_MEMSET
++extern void * memset(void * s,int c,size_t count);
++
++#if 0
++#define __HAVE_ARCH_BCOPY
++#define __HAVE_ARCH_STRLEN
++#endif
++
++#endif /* KERNEL */
++
++#endif /* !(__NIOS_STRING_H__) */
+--- linux/include/asm-nios2nommu/system.h
++++ linux/include/asm-nios2nommu/system.h
+@@ -0,0 +1,172 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SYSTEM_H
++#define _NIOS2NOMMU_SYSTEM_H
++
++// #include <linux/config.h> /* get configuration macros */
++#include <linux/linkage.h>
++#include <asm/segment.h>
++#include <asm/entry.h>
++#include <asm/nios.h>
++
++/*
++ * switch_to(n) should switch tasks to task ptr, first checking that
++ * ptr isn't the current task, in which case it does nothing. This
++ * also clears the TS-flag if the task we switched to has used the
++ * math co-processor latest.
++ */
++
++/*
++ */
++asmlinkage void resume(void);
++#define switch_to(prev,next,last) \
++{ \
++ void *_last; \
++ __asm__ __volatile__( \
++ "mov r4, %1\n" \
++ "mov r5, %2\n" \
++ "call resume\n" \
++ "mov %0,r4\n" \
++ : "=r" (_last) \
++ : "r" (prev), "r" (next) \
++ : "r4","r5","r7","r8","ra"); \
++ (last) = _last; \
++}
++
++#define local_irq_enable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "ori r8, r8, 1\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_irq_disable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "andi r8, r8, 0xfffe\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_save_flags(x) __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "mov %0, r8\n" \
++ :"=r" (x) : : "r8", "memory")
++
++#define local_irq_restore(x) __asm__ __volatile__ ( \
++ "mov r8, %0\n" \
++ "wrctl status, r8\n" \
++ : :"r" (x) : "memory")
++
++/* For spinlocks etc */
++#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
++
++#define irqs_disabled() \
++({ \
++ unsigned long flags; \
++ local_save_flags(flags); \
++ ((flags & NIOS2_STATUS_PIE_MSK) == 0x0); \
++})
++
++#define iret() __asm__ __volatile__ ("eret": : :"memory", "ea")
++
++/*
++ * Force strict CPU ordering.
++ * Not really required on m68k...
++ */
++#define nop() asm volatile ("nop"::)
++#define mb() asm volatile ("" : : :"memory")
++#define rmb() asm volatile ("" : : :"memory")
++#define wmb() asm volatile ("" : : :"memory")
++#define set_rmb(var, value) do { xchg(&var, value); } while (0)
++#define set_mb(var, value) set_rmb(var, value)
++#define set_wmb(var, value) do { var = value; wmb(); } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb() mb()
++#define smp_rmb() rmb()
++#define smp_wmb() wmb()
++#define smp_read_barrier_depends() read_barrier_depends()
++#else
++#define smp_mb() barrier()
++#define smp_rmb() barrier()
++#define smp_wmb() barrier()
++#define smp_read_barrier_depends() do { } while(0)
++#endif
++
++#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
++#define tas(ptr) (xchg((ptr),1))
++
++struct __xchg_dummy { unsigned long a[100]; };
++#define __xg(x) ((volatile struct __xchg_dummy *)(x))
++
++static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++{
++ unsigned long tmp, flags;
++
++ local_irq_save(flags);
++
++ switch (size) {
++ case 1:
++ __asm__ __volatile__( \
++ "ldb %0, %2\n" \
++ "stb %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 2:
++ __asm__ __volatile__( \
++ "ldh %0, %2\n" \
++ "sth %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 4:
++ __asm__ __volatile__( \
++ "ldw %0, %2\n" \
++ "stw %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ }
++ local_irq_restore(flags);
++ return tmp;
++}
++
++/*
++ * Atomic compare and exchange. Compare OLD with MEM, if identical,
++ * store NEW in MEM. Return the initial value in MEM. Success is
++ * indicated by comparing RETURN with OLD.
++ */
++#define __HAVE_ARCH_CMPXCHG 1
++
++static __inline__ unsigned long
++cmpxchg(volatile int *p, int old, int new)
++{
++ unsigned long flags;
++ int prev;
++
++ local_irq_save(flags);
++ if ((prev = *p) == old)
++ *p = new;
++ local_irq_restore(flags);
++ return(prev);
++}
++
++#endif /* _NIOS2NOMMU_SYSTEM_H */
+--- linux/include/asm-nios2nommu/termbits.h
++++ linux/include/asm-nios2nommu/termbits.h
+@@ -0,0 +1,199 @@
++#ifndef __ARCH_NIOS_TERMBITS_H__
++#define __ARCH_NIOS_TERMBITS_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termbits.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/posix_types.h>
++
++typedef unsigned char cc_t;
++typedef unsigned int speed_t;
++typedef unsigned int tcflag_t;
++
++#define NCCS 19
++struct termios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++};
++
++/* c_cc characters */
++#define VINTR 0
++#define VQUIT 1
++#define VERASE 2
++#define VKILL 3
++#define VEOF 4
++#define VTIME 5
++#define VMIN 6
++#define VSWTC 7
++#define VSTART 8
++#define VSTOP 9
++#define VSUSP 10
++#define VEOL 11
++#define VREPRINT 12
++#define VDISCARD 13
++#define VWERASE 14
++#define VLNEXT 15
++#define VEOL2 16
++
++
++/* c_iflag bits */
++#define IGNBRK 0000001
++#define BRKINT 0000002
++#define IGNPAR 0000004
++#define PARMRK 0000010
++#define INPCK 0000020
++#define ISTRIP 0000040
++#define INLCR 0000100
++#define IGNCR 0000200
++#define ICRNL 0000400
++#define IUCLC 0001000
++#define IXON 0002000
++#define IXANY 0004000
++#define IXOFF 0010000
++#define IMAXBEL 0020000
++#define IUTF8 0040000
++
++/* c_oflag bits */
++#define OPOST 0000001
++#define OLCUC 0000002
++#define ONLCR 0000004
++#define OCRNL 0000010
++#define ONOCR 0000020
++#define ONLRET 0000040
++#define OFILL 0000100
++#define OFDEL 0000200
++#define NLDLY 0000400
++#define NL0 0000000
++#define NL1 0000400
++#define CRDLY 0003000
++#define CR0 0000000
++#define CR1 0001000
++#define CR2 0002000
++#define CR3 0003000
++#define TABDLY 0014000
++#define TAB0 0000000
++#define TAB1 0004000
++#define TAB2 0010000
++#define TAB3 0014000
++#define XTABS 0014000
++#define BSDLY 0020000
++#define BS0 0000000
++#define BS1 0020000
++#define VTDLY 0040000
++#define VT0 0000000
++#define VT1 0040000
++#define FFDLY 0100000
++#define FF0 0000000
++#define FF1 0100000
++
++/* c_cflag bit meaning */
++#define CBAUD 0010017
++#define B0 0000000 /* hang up */
++#define B50 0000001
++#define B75 0000002
++#define B110 0000003
++#define B134 0000004
++#define B150 0000005
++#define B200 0000006
++#define B300 0000007
++#define B600 0000010
++#define B1200 0000011
++#define B1800 0000012
++#define B2400 0000013
++#define B4800 0000014
++#define B9600 0000015
++#define B19200 0000016
++#define B38400 0000017
++#define EXTA B19200
++#define EXTB B38400
++#define CSIZE 0000060
++#define CS5 0000000
++#define CS6 0000020
++#define CS7 0000040
++#define CS8 0000060
++#define CSTOPB 0000100
++#define CREAD 0000200
++#define PARENB 0000400
++#define PARODD 0001000
++#define HUPCL 0002000
++#define CLOCAL 0004000
++#define CBAUDEX 0010000
++#define B57600 0010001
++#define B115200 0010002
++#define B230400 0010003
++#define B460800 0010004
++#define B500000 0010005
++#define B576000 0010006
++#define B921600 0010007
++#define B1000000 0010010
++#define B1152000 0010011
++#define B1500000 0010012
++#define B2000000 0010013
++#define B2500000 0010014
++#define B3000000 0010015
++#define B3500000 0010016
++#define B4000000 0010017
++#define CIBAUD 002003600000 /* input baud rate (not used) */
++#define CMSPAR 010000000000 /* mark or space (stick) parity */
++#define CRTSCTS 020000000000 /* flow control */
++
++/* c_lflag bits */
++#define ISIG 0000001
++#define ICANON 0000002
++#define XCASE 0000004
++#define ECHO 0000010
++#define ECHOE 0000020
++#define ECHOK 0000040
++#define ECHONL 0000100
++#define NOFLSH 0000200
++#define TOSTOP 0000400
++#define ECHOCTL 0001000
++#define ECHOPRT 0002000
++#define ECHOKE 0004000
++#define FLUSHO 0010000
++#define PENDIN 0040000
++#define IEXTEN 0100000
++
++
++/* tcflow() and TCXONC use these */
++#define TCOOFF 0
++#define TCOON 1
++#define TCIOFF 2
++#define TCION 3
++
++/* tcflush() and TCFLSH use these */
++#define TCIFLUSH 0
++#define TCOFLUSH 1
++#define TCIOFLUSH 2
++
++/* tcsetattr uses these */
++#define TCSANOW 0
++#define TCSADRAIN 1
++#define TCSAFLUSH 2
++
++#endif /* __ARCH_NIOS_TERMBITS_H__ */
+--- linux/include/asm-nios2nommu/termios.h
++++ linux/include/asm-nios2nommu/termios.h
+@@ -0,0 +1,132 @@
++#ifndef _NIOS_TERMIOS_H
++#define _NIOS_TERMIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termios.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/termbits.h>
++#include <asm/ioctls.h>
++
++struct winsize {
++ unsigned short ws_row;
++ unsigned short ws_col;
++ unsigned short ws_xpixel;
++ unsigned short ws_ypixel;
++};
++
++#define NCC 8
++struct termio {
++ unsigned short c_iflag; /* input mode flags */
++ unsigned short c_oflag; /* output mode flags */
++ unsigned short c_cflag; /* control mode flags */
++ unsigned short c_lflag; /* local mode flags */
++ unsigned char c_line; /* line discipline */
++ unsigned char c_cc[NCC]; /* control characters */
++};
++
++#ifdef __KERNEL__
++/* intr=^C quit=^| erase=del kill=^U
++ eof=^D vtime=\0 vmin=\1 sxtc=\0
++ start=^Q stop=^S susp=^Z eol=\0
++ reprint=^R discard=^U werase=^W lnext=^V
++ eol2=\0
++*/
++#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
++#endif
++
++/* modem lines */
++#define TIOCM_LE 0x001
++#define TIOCM_DTR 0x002
++#define TIOCM_RTS 0x004
++#define TIOCM_ST 0x008
++#define TIOCM_SR 0x010
++#define TIOCM_CTS 0x020
++#define TIOCM_CAR 0x040
++#define TIOCM_RNG 0x080
++#define TIOCM_DSR 0x100
++#define TIOCM_CD TIOCM_CAR
++#define TIOCM_RI TIOCM_RNG
++#define TIOCM_OUT1 0x2000
++#define TIOCM_OUT2 0x4000
++#define TIOCM_LOOP 0x8000
++
++/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
++
++/* line disciplines */
++#define N_TTY 0
++#define N_SLIP 1
++#define N_MOUSE 2
++#define N_PPP 3
++#define N_STRIP 4
++#define N_AX25 5
++#define N_X25 6 /* X.25 async */
++#define N_6PACK 7
++#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
++#define N_R3964 9 /* Reserved for Simatic R3964 module */
++#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
++#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
++#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
++#define N_HDLC 13 /* synchronous HDLC */
++#define N_SYNC_PPP 14
++#define N_HCI 15 /* Bluetooth HCI UART */
++
++#ifdef __KERNEL__
++
++/*
++ * Translate a "termio" structure into a "termios". Ugh.
++ */
++#define user_termio_to_kernel_termios(termios, termio) \
++({ \
++ unsigned short tmp; \
++ get_user(tmp, &(termio)->c_iflag); \
++ (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
++ get_user(tmp, &(termio)->c_oflag); \
++ (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
++ get_user(tmp, &(termio)->c_cflag); \
++ (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
++ get_user(tmp, &(termio)->c_lflag); \
++ (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
++ get_user((termios)->c_line, &(termio)->c_line); \
++ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
++})
++
++/*
++ * Translate a "termios" structure into a "termio". Ugh.
++ */
++#define kernel_termios_to_user_termio(termio, termios) \
++({ \
++ put_user((termios)->c_iflag, &(termio)->c_iflag); \
++ put_user((termios)->c_oflag, &(termio)->c_oflag); \
++ put_user((termios)->c_cflag, &(termio)->c_cflag); \
++ put_user((termios)->c_lflag, &(termio)->c_lflag); \
++ put_user((termios)->c_line, &(termio)->c_line); \
++ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
++})
++
++#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TERMIOS_H */
+--- linux/include/asm-nios2nommu/thread_info.h
++++ linux/include/asm-nios2nommu/thread_info.h
+@@ -0,0 +1,127 @@
++/* thread_info.h: niosnommu low-level thread information
++ * adapted from the m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2002 Microtronix Datacom
++ *
++ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_THREAD_INFO_H
++#define _ASM_THREAD_INFO_H
++
++#include <asm/page.h>
++
++#ifdef __KERNEL__
++
++#ifndef __ASSEMBLY__
++
++/*
++ * low level task data.
++ */
++struct thread_info {
++ struct task_struct *task; /* main task structure */
++ struct exec_domain *exec_domain; /* execution domain */
++ unsigned long flags; /* low level flags */
++ int cpu; /* cpu we're on */
++ int preempt_count; /* 0 => preemptable, <0 => BUG*/
++ struct restart_block restart_block;
++};
++
++/*
++ * macros/functions for gaining access to the thread information structure
++ */
++#define INIT_THREAD_INFO(tsk) \
++{ \
++ .task = &tsk, \
++ .exec_domain = &default_exec_domain, \
++ .flags = 0, \
++ .cpu = 0, \
++ .preempt_count = 1, \
++ .restart_block = { \
++ .fn = do_no_restart_syscall, \
++ }, \
++}
++
++#define init_thread_info (init_thread_union.thread_info)
++#define init_stack (init_thread_union.stack)
++
++
++/* how to get the thread information struct from C
++ usable only in supervisor mode */
++static inline struct thread_info *current_thread_info(void)
++{
++ struct thread_info *ti;
++ __asm__ __volatile__(
++ "mov %0, sp\n"
++ "and %0, %0, %1\n"
++ : "=&r"(ti)
++ : "r" (~(THREAD_SIZE-1))
++ );
++ return ti;
++}
++
++/* thread information allocation */
++#define alloc_thread_info(tsk) ((struct thread_info *) \
++ __get_free_pages(GFP_KERNEL, 1))
++#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
++#define put_thread_info(ti) put_task_struct((ti)->task)
++
++#define PREEMPT_ACTIVE 0x4000000
++
++/*
++ * thread information flag bit numbers
++ */
++#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
++#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
++#define TIF_SIGPENDING 2 /* signal pending */
++#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
++#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
++ TIF_NEED_RESCHED */
++#define TIF_MEMDIE 5
++
++/* as above, but as bit values */
++#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
++#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
++#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
++#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
++
++#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
++
++#else /* __ASSEMBLY__ */
++
++/* how to get the thread information struct from ASM
++ usable only in supervisor mode */
++.macro GET_THREAD_INFO reg
++.if THREAD_SIZE & 0xffff0000
++ andhi \reg, sp, %hi(~(THREAD_SIZE-1))
++.else
++ addi \reg, r0, %lo(~(THREAD_SIZE-1))
++ and \reg, \reg, sp
++.endif
++.endm
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_THREAD_INFO_H */
+--- linux/include/asm-nios2nommu/timer_struct.h
++++ linux/include/asm-nios2nommu/timer_struct.h
+@@ -0,0 +1,38 @@
++
++// ----------------------------------------------
++// Timer Peripheral
++
++// Timer Registers
++typedef volatile struct
++ {
++ int np_timerstatus; // read only, 2 bits (any write to clear TO)
++ int np_timercontrol; // write/readable, 4 bits
++ int np_timerperiodl; // write/readable, 16 bits
++ int np_timerperiodh; // write/readable, 16 bits
++ int np_timersnapl; // read only, 16 bits
++ int np_timersnaph; // read only, 16 bits
++ } np_timer;
++
++// Timer Register Bits
++enum
++ {
++ np_timerstatus_run_bit = 1, // timer is running
++ np_timerstatus_to_bit = 0, // timer has timed out
++
++ np_timercontrol_stop_bit = 3, // stop the timer
++ np_timercontrol_start_bit = 2, // start the timer
++ np_timercontrol_cont_bit = 1, // continous mode
++ np_timercontrol_ito_bit = 0, // enable time out interrupt
++
++ np_timerstatus_run_mask = (1<<1), // timer is running
++ np_timerstatus_to_mask = (1<<0), // timer has timed out
++
++ np_timercontrol_stop_mask = (1<<3), // stop the timer
++ np_timercontrol_start_mask = (1<<2), // start the timer
++ np_timercontrol_cont_mask = (1<<1), // continous mode
++ np_timercontrol_ito_mask = (1<<0) // enable time out interrupt
++ };
++
++// Timer Routines
++int nr_timer_milliseconds(void); // Starts on first call, hogs timer1.
++
+--- linux/include/asm-nios2nommu/timex.h
++++ linux/include/asm-nios2nommu/timex.h
+@@ -0,0 +1,48 @@
++#ifndef _ASMNIOS2NOMMU_TIMEX_H
++#define _ASMNIOS2NOMMU_TIMEX_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/timex.h
++ *
++ * timex specifications
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++
++#define CLOCK_TICK_RATE nasys_clock_freq /* Underlying HZ */
++
++#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
++
++#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
++ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
++ << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
++
++typedef unsigned long cycles_t;
++
++static inline cycles_t get_cycles(void)
++{
++ return 0;
++}
++
++#endif
+--- linux/include/asm-nios2nommu/tlbflush.h
++++ linux/include/asm-nios2nommu/tlbflush.h
+@@ -0,0 +1,86 @@
++#ifndef _NIOS2NOMMU_TLBFLUSH_H
++#define _NIOS2NOMMU_TLBFLUSH_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlbflush.h
++ *
++ * Ported from m68knommu.
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm/setup.h>
++
++/*
++ * flush all user-space atc entries.
++ */
++static inline void __flush_tlb(void)
++{
++ BUG();
++}
++
++static inline void __flush_tlb_one(unsigned long addr)
++{
++ BUG();
++}
++
++#define flush_tlb() __flush_tlb()
++
++/*
++ * flush all atc entries (both kernel and user-space entries).
++ */
++static inline void flush_tlb_all(void)
++{
++ BUG();
++}
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++ BUG();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
++{
++ BUG();
++}
++
++static inline void flush_tlb_range(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_kernel_page(unsigned long addr)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_pgtables(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++#endif /* _NIOS2NOMMU_TLBFLUSH_H */
+--- linux/include/asm-nios2nommu/tlb.h
++++ linux/include/asm-nios2nommu/tlb.h
+@@ -0,0 +1,35 @@
++#ifndef __NIOS_TLB_H__
++#define __NIOS_TLB_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlb.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd
++ * Copyright (C) 2002 NEC Corporation
++ * Copyright (C) 2002 Miles Bader <miles@gnu.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Written by Miles Bader <miles@gnu.org>
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define tlb_flush(tlb) ((void)0)
++
++#include <asm-generic/tlb.h>
++
++#endif /* __NIOS_TLB_H__ */
++
+--- linux/include/asm-nios2nommu/topology.h
++++ linux/include/asm-nios2nommu/topology.h
+@@ -0,0 +1,30 @@
++#ifndef _ASM_NIOS2NOMMU_TOPOLOGY_H
++#define _ASM_NIOS2NOMMU_TOPOLOGY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/topology.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/topology.h>
++
++#endif /* _ASM_NIOS2NOMMU_TOPOLOGY_H */
+--- linux/include/asm-nios2nommu/traps.h
++++ linux/include/asm-nios2nommu/traps.h
+@@ -0,0 +1,27 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_TRAPS_H
++#define _NIOS2_TRAPS_H
++
++#define TRAP_ID_SYSCALL 0
++#define TRAP_ID_APPDEBUG 1
++#endif /* !(_NIOS2_TRAPS_H) */
+--- linux/include/asm-nios2nommu/types.h
++++ linux/include/asm-nios2nommu/types.h
+@@ -0,0 +1,93 @@
++#ifndef _NIOS_TYPES_H
++#define _NIOS_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/types.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is never included by application software unless
++ * explicitly requested (e.g., via linux/types.h) in which case the
++ * application is Linux specific so (user-) name space pollution is
++ * not a major issue. However, for interoperability, libraries still
++ * need to be careful to avoid a name clashes.
++ */
++
++#ifndef __ASSEMBLY__
++
++typedef unsigned short umode_t;
++
++/*
++ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
++ * header files exported to user space
++ */
++
++typedef __signed__ char __s8;
++typedef unsigned char __u8;
++
++typedef __signed__ short __s16;
++typedef unsigned short __u16;
++
++typedef __signed__ int __s32;
++typedef unsigned int __u32;
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++typedef __signed__ long long __s64;
++typedef unsigned long long __u64;
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * These aren't exported outside the kernel to avoid name space clashes
++ */
++#ifdef __KERNEL__
++
++#define BITS_PER_LONG 32
++
++#ifndef __ASSEMBLY__
++
++typedef signed char s8;
++typedef unsigned char u8;
++
++typedef signed short s16;
++typedef unsigned short u16;
++
++typedef signed int s32;
++typedef unsigned int u32;
++
++typedef signed long long s64;
++typedef unsigned long long u64;
++
++/* DMA addresses are always 32-bits wide */
++
++typedef u32 dma_addr_t;
++typedef u32 dma64_addr_t;
++
++typedef unsigned short kmem_bufctl_t;
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TYPES_H */
+--- linux/include/asm-nios2nommu/uaccess.h
++++ linux/include/asm-nios2nommu/uaccess.h
+@@ -0,0 +1,183 @@
++#ifndef __NIOS2NOMMU_UACCESS_H
++#define __NIOS2NOMMU_UACCESS_H
++
++/*--------------------------------------------------------------------
++ *
++ * asm-nios2nommu/uaccess.h
++ *
++ * User space memory access functions
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Ported from asm-m68knommu/uaccess.h --wentao
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <asm/segment.h>
++#include <asm/nios.h>
++
++#define VERIFY_READ 0
++#define VERIFY_WRITE 1
++
++#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
++
++static inline int _access_ok(unsigned long addr, unsigned long size)
++{
++ return (((unsigned long)addr < (unsigned long)nasys_program_mem_end) &&
++ (((unsigned long)addr >= (unsigned long)nasys_program_mem)));
++}
++
++extern inline int verify_area(int type, const void * addr, unsigned long size)
++{
++ return access_ok(type,addr,size)?0:-EFAULT;
++}
++
++/*
++ * The exception table consists of pairs of addresses: the first is the
++ * address of an instruction that is allowed to fault, and the second is
++ * the address at which the program should continue. No registers are
++ * modified, so it is entirely up to the continuation code to figure out
++ * what to do.
++ *
++ * All the routines below use bits of fixup code that are out of line
++ * with the main instruction path. This means when everything is well,
++ * we don't even have to jump over them. Further, they do not intrude
++ * on our cache or tlb entries.
++ */
++
++#define ARCH_HAS_SEARCH_EXTABLE
++//;dgt2;tmp;
++
++struct exception_table_entry
++{
++ unsigned long insn, fixup;
++};
++
++/* Returns 0 if exception not found and fixup otherwise. */
++extern unsigned long search_exception_table(unsigned long);
++
++
++/*
++ * These are the main single-value transfer routines. They automatically
++ * use the right size if we just have the right pointer type.
++ */
++
++#define put_user(x, ptr) \
++({ \
++ int __pu_err = 0; \
++ typeof(*(ptr)) __pu_val = (x); \
++ switch (sizeof (*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(ptr, &__pu_val, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __pu_err = __put_user_bad(); \
++ break; \
++ } \
++ __pu_err; \
++})
++#define __put_user(x, ptr) put_user(x, ptr)
++
++extern int __put_user_bad(void);
++
++/*
++ * Tell gcc we read from memory instead of writing: this is because
++ * we do not write to any memory gcc knows about, so there are no
++ * aliasing issues.
++ */
++
++#define __ptr(x) ((unsigned long *)(x))
++
++#define get_user(x, ptr) \
++({ \
++ int __gu_err = 0; \
++ typeof(*(ptr)) __gu_val = 0; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(&__gu_val, ptr, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __gu_val = 0; \
++ __gu_err = __get_user_bad(); \
++ break; \
++ } \
++ (x) = __gu_val; \
++ __gu_err; \
++})
++#define __get_user(x, ptr) get_user(x, ptr)
++
++extern int __get_user_bad(void);
++
++#define copy_from_user(to, from, n) (memcpy(to, from, n), 0)
++#define copy_to_user(to, from, n) (memcpy(to, from, n), 0)
++
++#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
++#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
++#define __copy_to_user_inatomic __copy_to_user
++#define __copy_from_user_inatomic __copy_from_user
++
++#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
++
++#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
++
++/*
++ * Copy a null terminated string from userspace.
++ */
++
++static inline long
++strncpy_from_user(char *dst, const char *src, long count)
++{
++ char *tmp;
++ strncpy(dst, src, count);
++ for (tmp = dst; *tmp && count > 0; tmp++, count--)
++ ;
++ return(tmp - dst); /* DAVIDM should we count a NUL ? check getname */
++}
++
++/*
++ * Return the size of a string (including the ending 0)
++ *
++ * Return 0 on exception, a value greater than N if too long
++ */
++static inline long strnlen_user(const char *src, long n)
++{
++ return(strlen(src) + 1); /* DAVIDM make safer */
++}
++
++#define strlen_user(str) strnlen_user(str, 32767)
++
++/*
++ * Zero Userspace
++ */
++
++static inline unsigned long
++clear_user(void *to, unsigned long n)
++{
++ memset(to, 0, n);
++ return(0);
++}
++
++#endif /* _NIOS2NOMMU_UACCESS_H */
+--- linux/include/asm-nios2nommu/uart_struct.h
++++ linux/include/asm-nios2nommu/uart_struct.h
+@@ -0,0 +1,83 @@
++
++// UART Registers
++typedef volatile struct
++ {
++ int np_uartrxdata; // Read-only, 8-bit
++ int np_uarttxdata; // Write-only, 8-bit
++ int np_uartstatus; // Read-only, 8-bit
++ int np_uartcontrol; // Read/Write, 9-bit
++ int np_uartdivisor; // Read/Write, 16-bit, optional
++ int np_uartendofpacket; // Read/Write, end-of-packet character
++ } np_uart;
++
++// UART Status Register Bits
++enum
++ {
++ np_uartstatus_eop_bit = 12,
++ np_uartstatus_cts_bit = 11,
++ np_uartstatus_dcts_bit = 10,
++ np_uartstatus_e_bit = 8,
++ np_uartstatus_rrdy_bit = 7,
++ np_uartstatus_trdy_bit = 6,
++ np_uartstatus_tmt_bit = 5,
++ np_uartstatus_toe_bit = 4,
++ np_uartstatus_roe_bit = 3,
++ np_uartstatus_brk_bit = 2,
++ np_uartstatus_fe_bit = 1,
++ np_uartstatus_pe_bit = 0,
++
++ np_uartstatus_eop_mask = (1<<12),
++ np_uartstatus_cts_mask = (1<<11),
++ np_uartstatus_dcts_mask = (1<<10),
++ np_uartstatus_e_mask = (1<<8),
++ np_uartstatus_rrdy_mask = (1<<7),
++ np_uartstatus_trdy_mask = (1<<6),
++ np_uartstatus_tmt_mask = (1<<5),
++ np_uartstatus_toe_mask = (1<<4),
++ np_uartstatus_roe_mask = (1<<3),
++ np_uartstatus_brk_mask = (1<<2),
++ np_uartstatus_fe_mask = (1<<1),
++ np_uartstatus_pe_mask = (1<<0)
++ };
++
++// UART Control Register Bits
++enum
++ {
++ np_uartcontrol_ieop_bit = 12,
++ np_uartcontrol_rts_bit = 11,
++ np_uartcontrol_idcts_bit = 10,
++ np_uartcontrol_tbrk_bit = 9,
++ np_uartcontrol_ie_bit = 8,
++ np_uartcontrol_irrdy_bit = 7,
++ np_uartcontrol_itrdy_bit = 6,
++ np_uartcontrol_itmt_bit = 5,
++ np_uartcontrol_itoe_bit = 4,
++ np_uartcontrol_iroe_bit = 3,
++ np_uartcontrol_ibrk_bit = 2,
++ np_uartcontrol_ife_bit = 1,
++ np_uartcontrol_ipe_bit = 0,
++
++ np_uartcontrol_ieop_mask = (1<<12),
++ np_uartcontrol_rts_mask = (1<<11),
++ np_uartcontrol_idcts_mask = (1<<10),
++ np_uartcontrol_tbrk_mask = (1<<9),
++ np_uartcontrol_ie_mask = (1<<8),
++ np_uartcontrol_irrdy_mask = (1<<7),
++ np_uartcontrol_itrdy_mask = (1<<6),
++ np_uartcontrol_itmt_mask = (1<<5),
++ np_uartcontrol_itoe_mask = (1<<4),
++ np_uartcontrol_iroe_mask = (1<<3),
++ np_uartcontrol_ibrk_mask = (1<<2),
++ np_uartcontrol_ife_mask = (1<<1),
++ np_uartcontrol_ipe_mask = (1<<0)
++ };
++
++// UART Routines
++int nr_uart_rxchar(np_uart *uartBase); // 0 for default UART
++void nr_uart_txcr(void);
++void nr_uart_txchar(int c,np_uart *uartBase); // 0 for default UART
++void nr_uart_txhex(int x); // 16 or 32 bits
++void nr_uart_txhex16(short x);
++void nr_uart_txhex32(long x);
++void nr_uart_txstring(char *s);
++
+--- linux/include/asm-nios2nommu/ucontext.h
++++ linux/include/asm-nios2nommu/ucontext.h
+@@ -0,0 +1,63 @@
++#ifndef _NIOSKNOMMU_UCONTEXT_H
++#define _NIOSKNOMMU_UCONTEXT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/ucontext.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++typedef int greg_t;
++#define NGREG 32
++typedef greg_t gregset_t[NGREG];
++
++#ifdef CONFIG_FPU
++typedef struct fpregset {
++ int f_pcr;
++ int f_psr;
++ int f_fpiaddr;
++ int f_fpregs[8][3];
++} fpregset_t;
++#endif
++
++struct mcontext {
++ int version;
++ int status_extension;
++ gregset_t gregs;
++#ifdef CONFIG_FPU
++ fpregset_t fpregs;
++#endif
++};
++
++#define MCONTEXT_VERSION 2
++
++struct ucontext {
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct mcontext uc_mcontext;
++#ifdef CONFIG_FPU
++ unsigned long uc_filler[80];
++#endif
++ sigset_t uc_sigmask; /* mask last for extensibility */
++};
++
++#endif
+--- linux/include/asm-nios2nommu/unaligned.h
++++ linux/include/asm-nios2nommu/unaligned.h
+@@ -0,0 +1,43 @@
++#ifndef __NIOS_UNALIGNED_H
++#define __NIOS_UNALIGNED_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/unaligned.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * The nios cannot do unaligned accesses itself.
++ */
++
++#define get_unaligned(ptr) ({ \
++ typeof((*(ptr))) x; \
++ memcpy(&x, (void*)ptr, sizeof(*(ptr))); \
++ x; \
++})
++
++#define put_unaligned(val, ptr) ({ \
++ typeof((*(ptr))) x = val; \
++ memcpy((void*)ptr, &x, sizeof(*(ptr))); \
++})
++
++#endif /* __NIOS_UNALIGNED_H */
+--- linux/include/asm-nios2nommu/unistd.h
++++ linux/include/asm-nios2nommu/unistd.h
+@@ -0,0 +1,686 @@
++#ifndef _ASM_NIOS_UNISTD_H_
++#define _ASM_NIOS_UNISTD_H_
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/unistd.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * //vic - kernel_thread moved to process.c
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/traps.h>
++
++/* TRAP isr expects the trap# (syscall=#TRAP_ID_SYSCALL) in r2,
++ * the syscall # in r3, and arguments in r4, r5, ...
++ * Return argument expected in r2.
++ */
++
++#define __NR_restart_syscall 0
++#define __NR_exit 1
++#define __NR_fork 2
++#define __NR_read 3
++#define __NR_write 4
++#define __NR_open 5
++#define __NR_close 6
++#define __NR_waitpid 7
++#define __NR_creat 8
++#define __NR_link 9
++#define __NR_unlink 10
++#define __NR_execve 11
++#define __NR_chdir 12
++#define __NR_time 13
++#define __NR_mknod 14
++#define __NR_chmod 15
++#define __NR_chown 16
++#define __NR_break 17
++#define __NR_oldstat 18
++#define __NR_lseek 19
++#define __NR_getpid 20
++#define __NR_mount 21
++#define __NR_umount 22
++#define __NR_setuid 23
++#define __NR_getuid 24
++#define __NR_stime 25
++#define __NR_ptrace 26
++#define __NR_alarm 27
++#define __NR_oldfstat 28
++#define __NR_pause 29
++#define __NR_utime 30
++#define __NR_stty 31
++#define __NR_gtty 32
++#define __NR_access 33
++#define __NR_nice 34
++#define __NR_ftime 35
++#define __NR_sync 36
++#define __NR_kill 37
++#define __NR_rename 38
++#define __NR_mkdir 39
++#define __NR_rmdir 40
++#define __NR_dup 41
++#define __NR_pipe 42
++#define __NR_times 43
++#define __NR_prof 44
++#define __NR_brk 45
++#define __NR_setgid 46
++#define __NR_getgid 47
++#define __NR_signal 48
++#define __NR_geteuid 49
++#define __NR_getegid 50
++#define __NR_acct 51
++#define __NR_umount2 52 //vic #define __NR_phys 52
++#define __NR_lock 53
++#define __NR_ioctl 54
++#define __NR_fcntl 55
++#define __NR_mpx 56
++#define __NR_setpgid 57
++#define __NR_ulimit 58
++#define __NR_oldolduname 59
++#define __NR_umask 60
++#define __NR_chroot 61
++#define __NR_ustat 62
++#define __NR_dup2 63
++#define __NR_getppid 64
++#define __NR_getpgrp 65
++#define __NR_setsid 66
++#define __NR_sigaction 67
++#define __NR_sgetmask 68
++#define __NR_ssetmask 69
++#define __NR_setreuid 70
++#define __NR_setregid 71
++#define __NR_sigsuspend 72
++#define __NR_sigpending 73
++#define __NR_sethostname 74
++#define __NR_setrlimit 75
++#define __NR_getrlimit 76
++#define __NR_getrusage 77
++#define __NR_gettimeofday 78
++#define __NR_settimeofday 79
++#define __NR_getgroups 80
++#define __NR_setgroups 81
++#define __NR_select 82
++#define __NR_symlink 83
++#define __NR_oldlstat 84
++#define __NR_readlink 85
++#define __NR_uselib 86
++#define __NR_swapon 87
++#define __NR_reboot 88
++#define __NR_readdir 89
++#define __NR_mmap 90
++#define __NR_munmap 91
++#define __NR_truncate 92
++#define __NR_ftruncate 93
++#define __NR_fchmod 94
++#define __NR_fchown 95
++#define __NR_getpriority 96
++#define __NR_setpriority 97
++#define __NR_profil 98
++#define __NR_statfs 99
++#define __NR_fstatfs 100
++#define __NR_ioperm 101
++#define __NR_socketcall 102
++#define __NR_syslog 103
++#define __NR_setitimer 104
++#define __NR_getitimer 105
++#define __NR_stat 106
++#define __NR_lstat 107
++#define __NR_fstat 108
++#define __NR_olduname 109
++#define __NR_iopl /* 110 */ not supported
++#define __NR_vhangup 111
++#define __NR_idle /* 112 */ Obsolete
++#define __NR_vm86 /* 113 */ not supported
++#define __NR_wait4 114
++#define __NR_swapoff 115
++#define __NR_sysinfo 116
++#define __NR_ipc 117
++#define __NR_fsync 118
++#define __NR_sigreturn 119
++#define __NR_clone 120
++#define __NR_setdomainname 121
++#define __NR_uname 122
++#define __NR_cacheflush 123
++#define __NR_adjtimex 124
++#define __NR_mprotect 125
++#define __NR_sigprocmask 126
++#define __NR_create_module 127
++#define __NR_init_module 128
++#define __NR_delete_module 129
++#define __NR_get_kernel_syms 130
++#define __NR_quotactl 131
++#define __NR_getpgid 132
++#define __NR_fchdir 133
++#define __NR_bdflush 134
++#define __NR_sysfs 135
++#define __NR_personality 136
++#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
++#define __NR_setfsuid 138
++#define __NR_setfsgid 139
++#define __NR__llseek 140
++#define __NR_getdents 141
++#define __NR__newselect 142
++#define __NR_flock 143
++#define __NR_msync 144
++#define __NR_readv 145
++#define __NR_writev 146
++#define __NR_getsid 147
++#define __NR_fdatasync 148
++#define __NR__sysctl 149
++#define __NR_mlock 150
++#define __NR_munlock 151
++#define __NR_mlockall 152
++#define __NR_munlockall 153
++#define __NR_sched_setparam 154
++#define __NR_sched_getparam 155
++#define __NR_sched_setscheduler 156
++#define __NR_sched_getscheduler 157
++#define __NR_sched_yield 158
++#define __NR_sched_get_priority_max 159
++#define __NR_sched_get_priority_min 160
++#define __NR_sched_rr_get_interval 161
++#define __NR_nanosleep 162
++#define __NR_mremap 163
++#define __NR_setresuid 164
++#define __NR_getresuid 165
++#define __NR_getpagesize 166
++#define __NR_query_module 167
++#define __NR_poll 168
++#define __NR_nfsservctl 169
++#define __NR_setresgid 170
++#define __NR_getresgid 171
++#define __NR_prctl 172
++#define __NR_rt_sigreturn 173
++#define __NR_rt_sigaction 174
++#define __NR_rt_sigprocmask 175
++#define __NR_rt_sigpending 176
++#define __NR_rt_sigtimedwait 177
++#define __NR_rt_sigqueueinfo 178
++#define __NR_rt_sigsuspend 179
++#define __NR_pread 180
++#define __NR_pwrite 181
++#define __NR_lchown 182
++#define __NR_getcwd 183
++#define __NR_capget 184
++#define __NR_capset 185
++#define __NR_sigaltstack 186
++#define __NR_sendfile 187
++#define __NR_getpmsg 188 /* some people actually want streams */
++#define __NR_putpmsg 189 /* some people actually want streams */
++#define __NR_vfork 190
++#define __NR_ugetrlimit 191
++#define __NR_mmap2 192
++#define __NR_truncate64 193
++#define __NR_ftruncate64 194
++#define __NR_stat64 195
++#define __NR_lstat64 196
++#define __NR_fstat64 197
++#define __NR_chown32 198
++#define __NR_getuid32 199
++#define __NR_getgid32 200
++#define __NR_geteuid32 201
++#define __NR_getegid32 202
++#define __NR_setreuid32 203
++#define __NR_setregid32 204
++#define __NR_getgroups32 205
++#define __NR_setgroups32 206
++#define __NR_fchown32 207
++#define __NR_setresuid32 208
++#define __NR_getresuid32 209
++#define __NR_setresgid32 210
++#define __NR_getresgid32 211
++#define __NR_lchown32 212
++#define __NR_setuid32 213
++#define __NR_setgid32 214
++#define __NR_setfsuid32 215
++#define __NR_setfsgid32 216
++#define __NR_pivot_root 217
++/* 218 unused */
++/* 219 unused */
++#define __NR_getdents64 220
++#define __NR_gettid 221
++#define __NR_tkill 222
++#define __NR_setxattr 223
++#define __NR_lsetxattr 224
++#define __NR_fsetxattr 225
++#define __NR_getxattr 226
++#define __NR_lgetxattr 227
++#define __NR_fgetxattr 228
++#define __NR_listxattr 229
++#define __NR_llistxattr 230
++#define __NR_flistxattr 231
++#define __NR_removexattr 232
++#define __NR_lremovexattr 233
++#define __NR_fremovexattr 234
++#define __NR_futex 235
++#define __NR_sendfile64 236
++#define __NR_mincore 237
++#define __NR_madvise 238
++#define __NR_fcntl64 239
++#define __NR_readahead 240
++#define __NR_io_setup 241
++#define __NR_io_destroy 242
++#define __NR_io_getevents 243
++#define __NR_io_submit 244
++#define __NR_io_cancel 245
++#define __NR_fadvise64 246
++#define __NR_exit_group 247
++#define __NR_lookup_dcookie 248
++#define __NR_epoll_create 249
++#define __NR_epoll_ctl 250
++#define __NR_epoll_wait 251
++#define __NR_remap_file_pages 252
++#define __NR_set_tid_address 253
++#define __NR_timer_create 254
++#define __NR_timer_settime 255
++#define __NR_timer_gettime 256
++#define __NR_timer_getoverrun 257
++#define __NR_timer_delete 258
++#define __NR_clock_settime 259
++#define __NR_clock_gettime 260
++#define __NR_clock_getres 261
++#define __NR_clock_nanosleep 262
++#define __NR_statfs64 263
++#define __NR_fstatfs64 264
++#define __NR_tgkill 265
++#define __NR_utimes 266
++#define __NR_fadvise64_64 267
++#define __NR_mbind 268
++#define __NR_get_mempolicy 269
++#define __NR_set_mempolicy 270
++#define __NR_mq_open 271
++#define __NR_mq_unlink 272
++#define __NR_mq_timedsend 273
++#define __NR_mq_timedreceive 274
++#define __NR_mq_notify 275
++#define __NR_mq_getsetattr 276
++#define __NR_waitid 277
++#define __NR_sys_setaltroot 278
++#define __NR_add_key 279
++#define __NR_request_key 280
++#define __NR_keyctl 281
++
++#define NR_syscalls 282
++
++/* user-visible error numbers are in the range -1 - -122: see
++ <asm-nios2nommu/errno.h> */
++
++#define __syscall_return(type, res) \
++do { \
++ if ((unsigned long)(res) >= (unsigned long)(-125)) { \
++ \
++ /* avoid using res which is declared to be in \
++ register r2; errno might expand to a function \
++ call and clobber it. */ \
++ \
++ int __err = -(res); \
++ errno = __err; \
++ res = -1; \
++ } \
++ return (type) (res); \
++} while (0)
++
++#define _syscall0(type,name) \
++type name(void) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall1 arg a
++//;dgt2;tmp; already being in r4 ?
++#define _syscall1(type,name,atype,a) \
++type name(atype a) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall2 args a,b
++//;dgt2;tmp; already being in r4,r5 ?
++#define _syscall2(type,name,atype,a,btype,b) \
++type name(atype a,btype b) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall3 args a,b,c
++//;dgt2;tmp; already being in r4,r5,r6 ?
++#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
++type name(atype a,btype b,ctype c) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall4 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
++type name (atype a, btype b, ctype c, dtype d) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) d */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall5 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
++type name (atype a,btype b,ctype c,dtype d,etype e) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) c */ \
++ " mov r8, %7\n\t" /* (long) e */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ , "r" ((long) e) /* %7 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ , "r8" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall6 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
++type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) c */ \
++ " mov r8, %7\n\t" /* (long) e */ \
++ " mov r9, %8\n\t" /* (long) f */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ , "r" ((long) e) /* %7 */ \
++ , "r" ((long) f) /* %8 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ , "r8" /* Clobbered */ \
++ , "r9" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++#ifdef __KERNEL__
++#define __ARCH_WANT_IPC_PARSE_VERSION
++#define __ARCH_WANT_OLD_READDIR
++#define __ARCH_WANT_OLD_STAT
++#define __ARCH_WANT_STAT64
++#define __ARCH_WANT_SYS_ALARM
++#define __ARCH_WANT_SYS_GETHOSTNAME
++#define __ARCH_WANT_SYS_PAUSE
++#define __ARCH_WANT_SYS_SGETMASK
++#define __ARCH_WANT_SYS_SIGNAL
++#define __ARCH_WANT_SYS_TIME
++#define __ARCH_WANT_SYS_UTIME
++#define __ARCH_WANT_SYS_WAITPID
++#define __ARCH_WANT_SYS_SOCKETCALL
++#define __ARCH_WANT_SYS_FADVISE64
++#define __ARCH_WANT_SYS_GETPGRP
++#define __ARCH_WANT_SYS_LLSEEK
++#define __ARCH_WANT_SYS_NICE
++#define __ARCH_WANT_SYS_OLD_GETRLIMIT
++#define __ARCH_WANT_SYS_OLDUMOUNT
++#define __ARCH_WANT_SYS_SIGPENDING
++#define __ARCH_WANT_SYS_SIGPROCMASK
++#define __ARCH_WANT_SYS_RT_SIGACTION
++#endif
++
++#ifdef __KERNEL_SYSCALLS__
++
++/*
++ * we need this inline - forking from kernel space will result
++ * in NO COPY ON WRITE (!!!), until an execve is executed. This
++ * is no problem, but for the stack. This is handled by not letting
++ * main() use the stack at all after fork(). Thus, no function
++ * calls - which means inline code for fork too, as otherwise we
++ * would use the stack upon exit from 'fork()'.
++ *
++ * Actually only pause and fork are needed inline, so that there
++ * won't be any messing with the stack from main(), but we define
++ * some others too.
++ */
++#define __NR__exit __NR_exit
++static inline _syscall0(int,pause)
++static inline _syscall0(int,sync)
++static inline _syscall0(pid_t,setsid)
++static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
++static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
++static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
++static inline _syscall1(int,dup,int,fd)
++static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
++static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
++static inline _syscall1(int,close,int,fd)
++static inline _syscall1(int,_exit,int,exitcode)
++static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
++static inline _syscall1(int,delete_module,const char *,name)
++
++static inline pid_t wait(int * wait_stat)
++{
++ return waitpid(-1,wait_stat,0);
++}
++
++#endif
++
++/*
++ * "Conditional" syscalls
++ *
++ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
++ * but it doesn't work on all toolchains, so we just do it by hand
++ */
++#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
++
++#endif /* _ASM_NIOS_UNISTD_H_ */
+--- linux/include/asm-nios2nommu/user.h
++++ linux/include/asm-nios2nommu/user.h
+@@ -0,0 +1,112 @@
++#ifndef _NIOS2NOMMU_USER_H
++#define _NIOS2NOMMU_USER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/user.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/page.h>
++
++/* Core file format: The core file is written in such a way that gdb
++ can understand it and provide useful information to the user (under
++ linux we use the 'trad-core' bfd). There are quite a number of
++ obstacles to being able to view the contents of the floating point
++ registers, and until these are solved you will not be able to view the
++ contents of them. Actually, you can read in the core file and look at
++ the contents of the user struct to find out what the floating point
++ registers contain.
++ The actual file contents are as follows:
++ UPAGE: 1 page consisting of a user struct that tells gdb what is present
++ in the file. Directly after this is a copy of the task_struct, which
++ is currently not used by gdb, but it may come in useful at some point.
++ All of the registers are stored as part of the upage. The upage should
++ always be only one page.
++ DATA: The data area is stored. We use current->end_text to
++ current->brk to pick up all of the user variables, plus any memory
++ that may have been malloced. No attempt is made to determine if a page
++ is demand-zero or if a page is totally unused, we just cover the entire
++ range. All of the addresses are rounded in such a way that an integral
++ number of pages is written.
++ STACK: We need the stack information in order to get a meaningful
++ backtrace. We need to write the data from (esp) to
++ current->start_stack, so we round each of these off in order to be able
++ to write an integer number of pages.
++ The minimum core file size is 3 pages, or 12288 bytes.
++*/
++
++struct user_m68kfp_struct {
++ unsigned long fpregs[8*3]; /* fp0-fp7 registers */
++ unsigned long fpcntl[3]; /* fp control regs */
++};
++
++/* This is needs more work, probably should look like gdb useage */
++struct user_regs_struct {
++ long r1,r2,r3,r4,r5,r6,r7,r8;
++ long r9,r10,r11,r12,r13,r14,r15;
++ long r16,r17,r18,r19,r20,r21,r22,r23;
++ long gp;
++ long sp;
++ long ra;
++ long fp;
++ long orig_r2;
++ long estatus;
++ long status_extension;
++ long ea;
++};
++
++
++/* When the kernel dumps core, it starts by dumping the user struct -
++ this will be used by gdb to figure out where the data and stack segments
++ are within the file, and what virtual addresses to use. */
++struct user{
++/* We start with the registers, to mimic the way that "memory" is returned
++ from the ptrace(3,...) function. */
++ struct user_regs_struct regs; /* Where the registers are actually stored */
++/* ptrace does not yet supply these. Someday.... */
++ int u_fpvalid; /* True if math co-processor being used. */
++ /* for this mess. Not yet used. */
++ struct user_m68kfp_struct m68kfp; /* Math Co-processor registers. */
++/* The rest of this junk is to help gdb figure out what goes where */
++ unsigned long int u_tsize; /* Text segment size (pages). */
++ unsigned long int u_dsize; /* Data segment size (pages). */
++ unsigned long int u_ssize; /* Stack segment size (pages). */
++ unsigned long start_code; /* Starting virtual address of text. */
++ unsigned long start_stack; /* Starting virtual address of stack area.
++ This is actually the bottom of the stack,
++ the top of the stack is always found in the
++ esp register. */
++ long int signal; /* Signal that caused the core dump. */
++ int reserved; /* No longer used */
++ struct user_regs_struct *u_ar0;
++ /* Used by gdb to help find the values for */
++ /* the registers. */
++ struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */
++ unsigned long magic; /* To uniquely identify a core file */
++ char u_comm[32]; /* User command that was responsible */
++};
++#define NBPG PAGE_SIZE
++#define UPAGES 1
++#define HOST_TEXT_START_ADDR (u.start_code)
++#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
++
++#endif
+--- linux/include/asm-nios2nommu/virtconvert.h
++++ linux/include/asm-nios2nommu/virtconvert.h
+@@ -0,0 +1,47 @@
++#ifndef __NIOS_VIRT_CONVERT__
++#define __NIOS_VIRT_CONVERT__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/virtconvert.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Macros used for converting between virtual and physical mappings.
++ */
++
++#ifdef __KERNEL__
++
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#endif /*__KERNEL__ */
++#endif /*__NIOS_VIRT_CONVERT__*/
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0-mips-nptl.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0-mips-nptl.patch
new file mode 100644
index 0000000000..72571b05e9
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0-mips-nptl.patch
@@ -0,0 +1,75 @@
+diff -urN linux-libc-headers-2.6.11.0/include/asm-mips/inst.h linux-libc-headers-2.6.11.0-nptl/include/asm-mips/inst.h
+--- linux-libc-headers-2.6.11.0/include/asm-mips/inst.h 2004-10-31 13:54:20.000000000 -0600
++++ linux-libc-headers-2.6.11.0-nptl/include/asm-mips/inst.h 2005-05-04 23:15:45.890613280 -0500
+@@ -28,7 +28,7 @@
+ sdl_op, sdr_op, swr_op, cache_op,
+ ll_op, lwc1_op, lwc2_op, pref_op,
+ lld_op, ldc1_op, ldc2_op, ld_op,
+- sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
++ sc_op, swc1_op, swc2_op, rdhwr_op,
+ scd_op, sdc1_op, sdc2_op, sd_op
+ };
+
+diff -urN linux-libc-headers-2.6.11.0/include/asm-mips/unistd.h linux-libc-headers-2.6.11.0-nptl/include/asm-mips/unistd.h
+--- linux-libc-headers-2.6.11.0/include/asm-mips/unistd.h 2005-01-08 08:02:51.000000000 -0600
++++ linux-libc-headers-2.6.11.0-nptl/include/asm-mips/unistd.h 2005-05-04 23:16:48.240229738 -0500
+@@ -303,16 +303,17 @@
+ #define __NR_add_key (__NR_Linux + 280)
+ #define __NR_request_key (__NR_Linux + 281)
+ #define __NR_keyctl (__NR_Linux + 282)
++#define __NR_set_thread_area (__NR_Linux + 283)
+
+ /*
+ * Offset of the last Linux o32 flavoured syscall
+ */
+-#define __NR_Linux_syscalls 282
++#define __NR_Linux_syscalls 283
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
+
+ #define __NR_O32_Linux 4000
+-#define __NR_O32_Linux_syscalls 282
++#define __NR_O32_Linux_syscalls 283
+
+ #if _MIPS_SIM == _MIPS_SIM_ABI64
+
+@@ -562,16 +563,17 @@
+ #define __NR_add_key (__NR_Linux + 239)
+ #define __NR_request_key (__NR_Linux + 240)
+ #define __NR_keyctl (__NR_Linux + 241)
++#define __NR_set_thread_area (__NR_Linux + 242)
+
+ /*
+ * Offset of the last Linux 64-bit flavoured syscall
+ */
+-#define __NR_Linux_syscalls 241
++#define __NR_Linux_syscalls 242
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+
+ #define __NR_64_Linux 5000
+-#define __NR_64_Linux_syscalls 241
++#define __NR_64_Linux_syscalls 242
+
+ #if _MIPS_SIM == _MIPS_SIM_NABI32
+
+@@ -825,16 +827,17 @@
+ #define __NR_add_key (__NR_Linux + 243)
+ #define __NR_request_key (__NR_Linux + 244)
+ #define __NR_keyctl (__NR_Linux + 245)
++#define __NR_set_thread_area (__NR_Linux + 246)
+
+ /*
+ * Offset of the last N32 flavoured syscall
+ */
+-#define __NR_Linux_syscalls 245
++#define __NR_Linux_syscalls 246
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+ #define __NR_N32_Linux 6000
+-#define __NR_N32_Linux_syscalls 245
++#define __NR_N32_Linux_syscalls 246
+
+ #ifndef __ASSEMBLY__
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0.patch
new file mode 100644
index 0000000000..f528b8b4c3
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.11.0.patch
@@ -0,0 +1,18 @@
+--- linux/include/linux/netfilter_ipv4/ip_nat.h.orig 2005-03-21 16:18:40.000000000 -0700
++++ linux/include/linux/netfilter_ipv4/ip_nat.h 2005-03-21 16:23:54.000000000 -0700
+@@ -66,6 +66,15 @@
+ struct ip_conntrack_manip manip;
+ };
+
++/* For backwards compat: don't use in modern code. */
++struct ip_nat_multi_range_compat
++{
++ unsigned int rangesize; /* Must be 1. */
++
++ /* hangs off end. */
++ struct ip_nat_range range[1];
++};
++
+ #define ip_nat_multi_range ip_nat_multi_range_compat
+
+ #endif
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-arm-eabi.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-arm-eabi.patch
new file mode 100644
index 0000000000..dcbd21b0a1
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-arm-eabi.patch
@@ -0,0 +1,166 @@
+--- linux-libc-headers-2.6.12.0/include/asm-arm/unistd.h 2005-07-06 03:17:41.000000000 +0300
++++ linux-libc-headers-2.6.12.0-arm-eabi/include/asm-arm/unistd.h 2006-06-05 17:14:09.000000000 +0300
+@@ -15,10 +15,12 @@
+
+ #include <linux/linkage.h>
+
+-#if defined(__thumb__)
++#define __NR_OABI_SYSCALL_BASE 0x900000
++
++#if defined(__thumb__) || defined(__ARM_EABI__)
+ #define __NR_SYSCALL_BASE 0
+ #else
+-#define __NR_SYSCALL_BASE 0x900000
++#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
+ #endif
+
+ /*
+@@ -365,13 +375,13 @@
+ #define __sys1(x) __sys2(x)
+
+ #ifndef __syscall
+-#if defined(__thumb__)
+-#define __syscall(name) \
+- "push {r7}\n\t" \
+- "mov r7, #" __sys1(__NR_##name) "\n\t" \
+- "swi 0\n\t" \
+- "pop {r7}"
++#if defined(__thumb__) || defined(__ARM_EABI__)
++#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name;
++#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
++#define __syscall(name) "swi\t0"
+ #else
++#define __SYS_REG(name)
++#define __SYS_REG_LIST(regs...) regs
+ #define __syscall(name) "swi\t" __sys1(__NR_##name) ""
+ #endif
+ #endif
+@@ -387,33 +397,34 @@
+
+ #define _syscall0(type,name) \
+ type name(void) { \
++ __SYS_REG(name) \
+ register long __res_r0 __asm__("r0"); \
+ long __res; \
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : \
+- : "lr"); \
++ : __SYS_REG_LIST() ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+
+ #define _syscall1(type,name,type1,arg1) \
+ type name(type1 arg1) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __res_r0 __asm__("r0"); \
+ long __res; \
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+ type name(type1 arg1,type2 arg2) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __r1 __asm__("r1") = (long)arg2; \
+ register long __res_r0 __asm__("r0"); \
+@@ -421,8 +432,7 @@
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0),"r" (__r1) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+@@ -430,6 +440,7 @@
+
+ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+ type name(type1 arg1,type2 arg2,type3 arg3) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __r1 __asm__("r1") = (long)arg2; \
+ register long __r2 __asm__("r2") = (long)arg3; \
+@@ -438,8 +449,7 @@
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0),"r" (__r1),"r" (__r2) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+@@ -447,6 +457,7 @@
+
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __r1 __asm__("r1") = (long)arg2; \
+ register long __r2 __asm__("r2") = (long)arg3; \
+@@ -456,8 +467,7 @@
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+@@ -465,6 +475,7 @@
+
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __r1 __asm__("r1") = (long)arg2; \
+ register long __r2 __asm__("r2") = (long)arg3; \
+@@ -475,14 +486,15 @@
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
++ "r" (__r3), "r" (__r4) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \
++ __SYS_REG(name) \
+ register long __r0 __asm__("r0") = (long)arg1; \
+ register long __r1 __asm__("r1") = (long)arg2; \
+ register long __r2 __asm__("r2") = (long)arg3; \
+@@ -494,14 +506,15 @@
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ : "=r" (__res_r0) \
+- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \
+- : "lr"); \
++ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
++ "r" (__r3), "r" (__r4), "r" (__r5) ) ); \
+ __res = __res_r0; \
+ __syscall_return(type,__res); \
+ }
+
+ #ifdef __KERNEL_SYSCALLS__
+
++#include <linux/compiler.h>
+ #include <linux/types.h>
+ #include <linux/syscalls.h>
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-config-base-small.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-config-base-small.patch
new file mode 100644
index 0000000000..b6bbfd64ab
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-config-base-small.patch
@@ -0,0 +1,30 @@
+diff -urN linux-libc-headers-2.6.12.0/include/linux/threads.h linux-libc-headers-2.6.12.0-patched/include/linux/threads.h
+--- linux-libc-headers-2.6.12.0/include/linux/threads.h 2005-07-05 19:17:23.000000000 -0500
++++ linux-libc-headers-2.6.12.0-patched/include/linux/threads.h 2005-08-18 11:39:15.000000000 -0500
+@@ -24,12 +24,11 @@
+ /*
+ * This controls the default maximum pid allocated to a process
+ */
+-#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
++#define PID_MAX_DEFAULT 0x8000
+
+ /*
+ * A maximum of 4 million PIDs should be enough for a while:
+ */
+-#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
+- (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
++#define PID_MAX_LIMIT (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT)
+
+ #endif
+diff -urN linux-libc-headers-2.6.12.0/include/linux/vt_kern.h linux-libc-headers-2.6.12.0-patched/include/linux/vt_kern.h
+--- linux-libc-headers-2.6.12.0/include/linux/vt_kern.h 2005-07-05 19:17:23.000000000 -0500
++++ linux-libc-headers-2.6.12.0-patched/include/linux/vt_kern.h 2005-08-18 11:39:30.000000000 -0500
+@@ -77,7 +77,7 @@
+ * we can easily avoid touching user space while holding the console spinlock.
+ */
+
+-#define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
++#define CON_BUF_SIZE PAGE_SIZE
+ extern char con_buf[CON_BUF_SIZE];
+ extern struct semaphore con_buf_sem;
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-i2c_msg.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-i2c_msg.patch
new file mode 100644
index 0000000000..2c1eac3f8b
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-i2c_msg.patch
@@ -0,0 +1,12 @@
+diff -urpN linux-libc-headers-2.6.12.0/include/linux/i2c-dev.h linux-libc-headers-2.6.12.0-patched/include/linux/i2c-dev.h
+--- linux-libc-headers-2.6.12.0/include/linux/i2c-dev.h 2005-07-06 02:17:21.000000000 +0200
++++ linux-libc-headers-2.6.12.0-patched/include/linux/i2c-dev.h 2006-04-26 13:10:56.000000000 +0200
+@@ -44,8 +44,6 @@ struct i2c_msg {
+ #define I2C_M_NO_RD_ACK 0x0800
+ short len; /* msg length */
+ char *buf; /* pointer to msg data */
+- int err;
+- short done;
+ };
+
+ /* To determine what functionality is present */
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-mips-nptl.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-mips-nptl.patch
new file mode 100644
index 0000000000..5f7167b62b
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.12.0-mips-nptl.patch
@@ -0,0 +1,90 @@
+diff -urN linux-libc-headers-2.6.12.0/include/asm-mips/inst.h linux-libc-headers-2.6.12.0-mips-nptl/include/asm-mips/inst.h
+--- linux-libc-headers-2.6.12.0/include/asm-mips/inst.h 2004-10-31 13:54:20.000000000 -0600
++++ linux-libc-headers-2.6.12.0-mips-nptl/include/asm-mips/inst.h 2005-08-10 21:20:57.000000000 -0500
+@@ -28,7 +28,7 @@
+ sdl_op, sdr_op, swr_op, cache_op,
+ ll_op, lwc1_op, lwc2_op, pref_op,
+ lld_op, ldc1_op, ldc2_op, ld_op,
+- sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
++ sc_op, swc1_op, swc2_op, rdhwr_op,
+ scd_op, sdc1_op, sdc2_op, sd_op
+ };
+
+@@ -62,10 +62,10 @@
+ spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
+ tgei_op, tgeiu_op, tlti_op, tltiu_op,
+ teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
+- bltzal_op, bgezal_op, bltzall_op, bgezall_op
+- /*
+- * The others (0x14 - 0x1f) are unused.
+- */
++ bltzal_op, bgezal_op, bltzall_op, bgezall_op,
++ rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
++ rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
++ bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
+ };
+
+ /*
+diff -urN linux-libc-headers-2.6.12.0/include/asm-mips/unistd.h linux-libc-headers-2.6.12.0-mips-nptl/include/asm-mips/unistd.h
+--- linux-libc-headers-2.6.12.0/include/asm-mips/unistd.h 2005-07-05 19:17:29.000000000 -0500
++++ linux-libc-headers-2.6.12.0-mips-nptl/include/asm-mips/unistd.h 2005-08-10 21:22:27.000000000 -0500
+@@ -303,16 +303,17 @@
+ #define __NR_add_key (__NR_Linux + 280)
+ #define __NR_request_key (__NR_Linux + 281)
+ #define __NR_keyctl (__NR_Linux + 282)
++#define __NR_set_thread_area (__NR_Linux + 283)
+
+ /*
+ * Offset of the last Linux o32 flavoured syscall
+ */
+-#define __NR_Linux_syscalls 282
++#define __NR_Linux_syscalls 283
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
+
+ #define __NR_O32_Linux 4000
+-#define __NR_O32_Linux_syscalls 282
++#define __NR_O32_Linux_syscalls 283
+
+ #if _MIPS_SIM == _MIPS_SIM_ABI64
+
+@@ -562,16 +563,17 @@
+ #define __NR_add_key (__NR_Linux + 239)
+ #define __NR_request_key (__NR_Linux + 240)
+ #define __NR_keyctl (__NR_Linux + 241)
++#define __NR_set_thread_area (__NR_Linux + 242)
+
+ /*
+ * Offset of the last Linux 64-bit flavoured syscall
+ */
+-#define __NR_Linux_syscalls 241
++#define __NR_Linux_syscalls 242
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+
+ #define __NR_64_Linux 5000
+-#define __NR_64_Linux_syscalls 241
++#define __NR_64_Linux_syscalls 242
+
+ #if _MIPS_SIM == _MIPS_SIM_NABI32
+
+@@ -825,16 +827,17 @@
+ #define __NR_add_key (__NR_Linux + 243)
+ #define __NR_request_key (__NR_Linux + 244)
+ #define __NR_keyctl (__NR_Linux + 245)
++#define __NR_set_thread_area (__NR_Linux + 246)
+
+ /*
+ * Offset of the last N32 flavoured syscall
+ */
+-#define __NR_Linux_syscalls 245
++#define __NR_Linux_syscalls 246
+
+ #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+ #define __NR_N32_Linux 6000
+-#define __NR_N32_Linux_syscalls 245
++#define __NR_N32_Linux_syscalls 246
+
+ #ifndef __ASSEMBLY__
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.8-cleanup.patch b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.8-cleanup.patch
new file mode 100644
index 0000000000..44461d1abf
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.8-cleanup.patch
@@ -0,0 +1,8153 @@
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/addrspace.h linux-libc-headers-2.6.8.0/include/asm-mips/addrspace.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/addrspace.h 2004-03-28 07:51:50.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/addrspace.h 2004-08-26 05:53:12.000000000 -0500
+@@ -10,7 +10,23 @@
+ #ifndef _ASM_ADDRSPACE_H
+ #define _ASM_ADDRSPACE_H
+
+-#include <spaces.h>
++/**********************************************************************/
++/* Include the common bits for #include <spaces.h> */
++#ifndef __mips64
++
++#define CAC_BASE 0x80000000
++#define IO_BASE 0xa0000000
++#define UNCAC_BASE 0xa0000000
++#define MAP_BASE 0xc0000000
++
++/*
++ * This handles the memory map.
++ * We handle pages at KSEG0 for kernels with 32 bit address space.
++ */
++#define PAGE_OFFSET 0x80000000UL
++
++#endif /* ndef __mips64 */
++/**********************************************************************/
+
+ /*
+ * Configure language
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/asmmacro.h linux-libc-headers-2.6.8.0/include/asm-mips/asmmacro.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/asmmacro.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/asmmacro.h 2004-08-26 05:14:41.000000000 -0500
+@@ -9,10 +9,10 @@
+ #define _ASM_ASMMACRO_H
+
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #include <asm/asmmacro-32.h>
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ #include <asm/asmmacro-64.h>
+ #endif
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/checksum.h linux-libc-headers-2.6.8.0/include/asm-mips/checksum.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/checksum.h 2004-06-23 16:52:45.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/checksum.h 2004-08-26 05:14:41.000000000 -0500
+@@ -125,7 +125,7 @@
+ {
+ __asm__(
+ ".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ "addu\t%0, %2\n\t"
+ "sltu\t$1, %0, %2\n\t"
+ "addu\t%0, $1\n\t"
+@@ -138,7 +138,7 @@
+ "sltu\t$1, %0, %4\n\t"
+ "addu\t%0, $1\n\t"
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ "daddu\t%0, %2\n\t"
+ "daddu\t%0, %3\n\t"
+ "daddu\t%0, %4\n\t"
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/compat.h linux-libc-headers-2.6.8.0/include/asm-mips/compat.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/compat.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/compat.h 2004-08-26 05:23:05.000000000 -0500
+@@ -8,64 +8,64 @@
+
+ #define COMPAT_USER_HZ 100
+
+-typedef u32 compat_size_t;
+-typedef s32 compat_ssize_t;
+-typedef s32 compat_time_t;
+-typedef s32 compat_clock_t;
+-typedef s32 compat_suseconds_t;
+-
+-typedef s32 compat_pid_t;
+-typedef s32 compat_uid_t;
+-typedef s32 compat_gid_t;
+-typedef u32 compat_mode_t;
+-typedef u32 compat_ino_t;
+-typedef u32 compat_dev_t;
+-typedef s32 compat_off_t;
+-typedef s64 compat_loff_t;
+-typedef u32 compat_nlink_t;
+-typedef s32 compat_ipc_pid_t;
+-typedef s32 compat_daddr_t;
+-typedef s32 compat_caddr_t;
++typedef __u32 compat_size_t;
++typedef __s32 compat_ssize_t;
++typedef __s32 compat_time_t;
++typedef __s32 compat_clock_t;
++typedef __s32 compat_suseconds_t;
++
++typedef __s32 compat_pid_t;
++typedef __s32 compat_uid_t;
++typedef __s32 compat_gid_t;
++typedef __u32 compat_mode_t;
++typedef __u32 compat_ino_t;
++typedef __u32 compat_dev_t;
++typedef __s32 compat_off_t;
++typedef __s64 compat_loff_t;
++typedef __u32 compat_nlink_t;
++typedef __s32 compat_ipc_pid_t;
++typedef __s32 compat_daddr_t;
++typedef __s32 compat_caddr_t;
+ typedef struct {
+- s32 val[2];
++ __s32 val[2];
+ } compat_fsid_t;
+
+-typedef s32 compat_int_t;
+-typedef s32 compat_long_t;
+-typedef u32 compat_uint_t;
+-typedef u32 compat_ulong_t;
++typedef __s32 compat_int_t;
++typedef __s32 compat_long_t;
++typedef __u32 compat_uint_t;
++typedef __u32 compat_ulong_t;
+
+ struct compat_timespec {
+ compat_time_t tv_sec;
+- s32 tv_nsec;
++ __s32 tv_nsec;
+ };
+
+ struct compat_timeval {
+ compat_time_t tv_sec;
+- s32 tv_usec;
++ __s32 tv_usec;
+ };
+
+ struct compat_stat {
+ compat_dev_t st_dev;
+- s32 st_pad1[3];
++ __s32 st_pad1[3];
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ compat_uid_t st_uid;
+ compat_gid_t st_gid;
+ compat_dev_t st_rdev;
+- s32 st_pad2[2];
++ __s32 st_pad2[2];
+ compat_off_t st_size;
+- s32 st_pad3;
++ __s32 st_pad3;
+ compat_time_t st_atime;
+- s32 st_atime_nsec;
++ __s32 st_atime_nsec;
+ compat_time_t st_mtime;
+- s32 st_mtime_nsec;
++ __s32 st_mtime_nsec;
+ compat_time_t st_ctime;
+- s32 st_ctime_nsec;
+- s32 st_blksize;
+- s32 st_blocks;
+- s32 st_pad4[14];
++ __s32 st_ctime_nsec;
++ __s32 st_blksize;
++ __s32 st_blocks;
++ __s32 st_pad4[14];
+ };
+
+ struct compat_flock {
+@@ -73,10 +73,10 @@
+ short l_whence;
+ compat_off_t l_start;
+ compat_off_t l_len;
+- s32 l_sysid;
++ __s32 l_sysid;
+ compat_pid_t l_pid;
+ short __unused;
+- s32 pad[4];
++ __s32 pad[4];
+ };
+
+ #define F_GETLK64 33
+@@ -107,12 +107,12 @@
+
+ #define COMPAT_RLIM_INFINITY 0x7fffffffUL
+
+-typedef u32 compat_old_sigset_t; /* at least 32 bits */
++typedef __u32 compat_old_sigset_t; /* at least 32 bits */
+
+ #define _COMPAT_NSIG 128 /* Don't ask !$@#% ... */
+ #define _COMPAT_NSIG_BPW 32
+
+-typedef u32 compat_sigset_word;
++typedef __u32 compat_sigset_word;
+
+ #define COMPAT_OFF_T_MAX 0x7fffffff
+ #define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+@@ -123,7 +123,7 @@
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+-typedef u32 compat_uptr_t;
++typedef __u32 compat_uptr_t;
+
+ static inline void *compat_ptr(compat_uptr_t uptr)
+ {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5074.h linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5074.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5074.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5074.h 2004-08-26 13:21:48.000000000 -0500
+@@ -34,5 +34,5 @@
+ extern void ddb5074_led_d2(int on);
+ extern void ddb5074_led_d3(int on);
+
+-extern void nile4_irq_setup(u32 base);
++extern void nile4_irq_setup(__u32 base);
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5476.h linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5476.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5476.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5476.h 2004-08-26 05:24:06.000000000 -0500
+@@ -145,13 +145,13 @@
+ extern void nile4_enable_irq(int nile4_irq);
+ extern void nile4_disable_irq(int nile4_irq);
+ extern void nile4_disable_irq_all(void);
+-extern u16 nile4_get_irq_stat(int cpu_irq);
++extern __u16 nile4_get_irq_stat(int cpu_irq);
+ extern void nile4_enable_irq_output(int cpu_irq);
+ extern void nile4_disable_irq_output(int cpu_irq);
+ extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
+ extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
+ extern void nile4_clear_irq(int nile4_irq);
+-extern void nile4_clear_irq_mask(u32 mask);
+-extern u8 nile4_i8259_iack(void);
++extern void nile4_clear_irq_mask(__u32 mask);
++extern __u8 nile4_i8259_iack(void);
+ extern void nile4_dump_irq_status(void); /* Debug */
+ #endif /* !__ASSEMBLY__ */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5xxx.h linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5xxx.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/ddb5xxx/ddb5xxx.h 2004-01-17 17:03:47.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/ddb5xxx/ddb5xxx.h 2004-08-26 05:24:01.000000000 -0500
+@@ -177,46 +177,46 @@
+ * interrupt load
+ */
+ #ifndef CONFIG_DDB5074
+- volatile u32 *p = (volatile u32 *)0xbfc00000;
++ volatile __u32 *p = (volatile __u32 *)0xbfc00000;
+ (void)(*p);
+ #endif
+ }
+
+-static inline void ddb_out32(u32 offset, u32 val)
++static inline void ddb_out32(__u32 offset, __u32 val)
+ {
+- *(volatile u32 *)(DDB_BASE+offset) = val;
++ *(volatile __u32 *)(DDB_BASE+offset) = val;
+ ddb_sync();
+ }
+
+-static inline u32 ddb_in32(u32 offset)
++static inline __u32 ddb_in32(__u32 offset)
+ {
+- u32 val = *(volatile u32 *)(DDB_BASE+offset);
++ __u32 val = *(volatile __u32 *)(DDB_BASE+offset);
+ ddb_sync();
+ return val;
+ }
+
+-static inline void ddb_out16(u32 offset, u16 val)
++static inline void ddb_out16(__u32 offset, __u16 val)
+ {
+- *(volatile u16 *)(DDB_BASE+offset) = val;
++ *(volatile __u16 *)(DDB_BASE+offset) = val;
+ ddb_sync();
+ }
+
+-static inline u16 ddb_in16(u32 offset)
++static inline __u16 ddb_in16(__u32 offset)
+ {
+- u16 val = *(volatile u16 *)(DDB_BASE+offset);
++ __u16 val = *(volatile __u16 *)(DDB_BASE+offset);
+ ddb_sync();
+ return val;
+ }
+
+-static inline void ddb_out8(u32 offset, u8 val)
++static inline void ddb_out8(__u32 offset, __u8 val)
+ {
+- *(volatile u8 *)(DDB_BASE+offset) = val;
++ *(volatile __u8 *)(DDB_BASE+offset) = val;
+ ddb_sync();
+ }
+
+-static inline u8 ddb_in8(u32 offset)
++static inline __u8 ddb_in8(__u32 offset)
+ {
+- u8 val = *(volatile u8 *)(DDB_BASE+offset);
++ __u8 val = *(volatile __u8 *)(DDB_BASE+offset);
+ ddb_sync();
+ return val;
+ }
+@@ -226,10 +226,10 @@
+ * Physical Device Address Registers
+ */
+
+-extern u32
+-ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible);
++extern __u32
++ddb_calc_pdar(__u32 phys, __u32 size, int width, int on_memory_bus, int pci_visible);
+ extern void
+-ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
++ddb_set_pdar(__u32 pdar, __u32 phys, __u32 size, int width,
+ int on_memory_bus, int pci_visible);
+
+ /*
+@@ -248,7 +248,7 @@
+ #define DDB_PCI_ACCESS_32 0x10 /* for pci init0/1 regs */
+
+
+-extern void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options);
++extern void ddb_set_pmr(__u32 pmr, __u32 type, __u32 addr, __u32 options);
+
+ /*
+ * we need to reset pci bus when we start up and shutdown
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/dec/ioasic.h linux-libc-headers-2.6.8.0/include/asm-mips/dec/ioasic.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/dec/ioasic.h 2004-01-17 17:03:47.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/dec/ioasic.h 2004-08-26 05:25:44.000000000 -0500
+@@ -18,14 +18,14 @@
+
+ extern spinlock_t ioasic_ssr_lock;
+
+-extern volatile u32 *ioasic_base;
++extern volatile __u32 *ioasic_base;
+
+-static inline void ioasic_write(unsigned int reg, u32 v)
++static inline void ioasic_write(unsigned int reg, __u32 v)
+ {
+ ioasic_base[reg / 4] = v;
+ }
+
+-static inline u32 ioasic_read(unsigned int reg)
++static inline __u32 ioasic_read(unsigned int reg)
+ {
+ return ioasic_base[reg / 4];
+ }
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/dec/kn02.h linux-libc-headers-2.6.8.0/include/asm-mips/dec/kn02.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/dec/kn02.h 2004-01-17 17:03:47.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/dec/kn02.h 2004-08-26 05:25:47.000000000 -0500
+@@ -97,7 +97,7 @@
+
+
+ #ifndef __ASSEMBLY__
+-extern u32 cached_kn02_csr;
++extern __u32 cached_kn02_csr;
+ extern spinlock_t kn02_lock;
+ extern void init_kn02_irqs(int base);
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/elf.h linux-libc-headers-2.6.8.0/include/asm-mips/elf.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/elf.h 2004-03-28 07:51:51.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/elf.h 2004-08-26 05:17:25.000000000 -0500
+@@ -122,7 +122,7 @@
+ typedef double elf_fpreg_t;
+ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+
+ /*
+ * This is used to ensure we don't load something for the wrong architecture.
+@@ -150,9 +150,9 @@
+ */
+ #define ELF_CLASS ELFCLASS32
+
+-#endif /* CONFIG_MIPS32 */
++#endif /* ndef __mips64 */
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ /*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+@@ -174,7 +174,7 @@
+ */
+ #define ELF_CLASS ELFCLASS64
+
+-#endif /* CONFIG_MIPS64 */
++#endif /* __mips64 */
+
+ /*
+ * These are used to set parameters in the core dumps.
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/galileo-boards/ev96100.h linux-libc-headers-2.6.8.0/include/asm-mips/galileo-boards/ev96100.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/galileo-boards/ev96100.h 2004-03-28 07:51:53.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/galileo-boards/ev96100.h 2004-08-26 05:23:12.000000000 -0500
+@@ -46,9 +46,9 @@
+ * bytes when running bigendian.
+ */
+ #define __GT_READ(ofs) \
+- (*(volatile u32 *)(GT64120_BASE+(ofs)))
++ (*(volatile __u32 *)(GT64120_BASE+(ofs)))
+ #define __GT_WRITE(ofs, data) \
+- do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
++ do { *(volatile __u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
+ #define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs))
+ #define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data))
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/galileo-boards/gt96100.h linux-libc-headers-2.6.8.0/include/asm-mips/galileo-boards/gt96100.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/galileo-boards/gt96100.h 2004-03-28 07:51:53.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/galileo-boards/gt96100.h 2004-08-26 05:23:17.000000000 -0500
+@@ -27,9 +27,9 @@
+ #define MIPS_GT96100_BASE (KSEG1ADDR(0x14000000))
+
+ #define GT96100_WRITE(ofs, data) \
+- *(volatile u32 *)(MIPS_GT96100_BASE+ofs) = cpu_to_le32(data)
++ *(volatile __u32 *)(MIPS_GT96100_BASE+ofs) = cpu_to_le32(data)
+ #define GT96100_READ(ofs) \
+- le32_to_cpu(*(volatile u32 *)(MIPS_GT96100_BASE+ofs))
++ le32_to_cpu(*(volatile __u32 *)(MIPS_GT96100_BASE+ofs))
+
+ #define GT96100_ETH_IO_SIZE 0x4000
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/gt64120.h linux-libc-headers-2.6.8.0/include/asm-mips/gt64120.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/gt64120.h 2004-03-28 07:51:51.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/gt64120.h 2004-08-26 05:22:36.000000000 -0500
+@@ -420,9 +420,9 @@
+ * bytes when running bigendian. We also provide non-swapping versions.
+ */
+ #define __GT_READ(ofs) \
+- (*(volatile u32 *)(GT64120_BASE+(ofs)))
++ (*(volatile __u32 *)(GT64120_BASE+(ofs)))
+ #define __GT_WRITE(ofs, data) \
+- do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
++ do { *(volatile __u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
+ #define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs))
+ #define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data))
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/io.h linux-libc-headers-2.6.8.0/include/asm-mips/io.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/io.h 2004-03-28 07:51:51.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/io.h 2004-08-26 05:24:16.000000000 -0500
+@@ -173,14 +173,14 @@
+ unsigned long flags)
+ {
+ if (cpu_has_64bit_addresses) {
+- u64 base = UNCAC_BASE;
++ __u64 base = UNCAC_BASE;
+
+ /*
+ * R10000 supports a 2 bit uncached attribute therefore
+ * UNCAC_BASE may not equal IO_BASE.
+ */
+ if (flags == _CACHE_UNCACHED)
+- base = (u64) IO_BASE;
++ base = (__u64) IO_BASE;
+ return (void *) (unsigned long) (base + offset);
+ }
+
+@@ -245,10 +245,10 @@
+ #define __raw_readb(addr) (*(volatile unsigned char *)(addr))
+ #define __raw_readw(addr) (*(volatile unsigned short *)(addr))
+ #define __raw_readl(addr) (*(volatile unsigned int *)(addr))
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #define ____raw_readq(addr) \
+ ({ \
+- u64 __res; \
++ __u64 __res; \
+ \
+ __asm__ __volatile__ ( \
+ " .set mips3 # ____raw_readq \n" \
+@@ -263,7 +263,7 @@
+ #define __raw_readq(addr) \
+ ({ \
+ unsigned long __flags; \
+- u64 __res; \
++ __u64 __res; \
+ \
+ local_irq_save(__flags); \
+ __res = ____raw_readq(addr); \
+@@ -271,7 +271,7 @@
+ __res; \
+ })
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ #define ____raw_readq(addr) (*(volatile unsigned long *)(addr))
+ #define __raw_readq(addr) ____raw_readq(addr)
+ #endif
+@@ -288,10 +288,10 @@
+ #define __raw_writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (b))
+ #define __raw_writew(w,addr) ((*(volatile unsigned short *)(addr)) = (w))
+ #define __raw_writel(l,addr) ((*(volatile unsigned int *)(addr)) = (l))
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #define ____raw_writeq(val,addr) \
+ ({ \
+- u64 __tmp; \
++ __u64 __tmp; \
+ \
+ __asm__ __volatile__ ( \
+ " .set mips3 \n" \
+@@ -313,7 +313,7 @@
+ local_irq_restore(__flags); \
+ })
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ #define ____raw_writeq(q,addr) ((*(volatile unsigned long *)(addr)) = (q))
+ #define __raw_writeq(q,addr) ____raw_writeq(q, addr)
+ #endif
+@@ -400,28 +400,28 @@
+ {
+ port = __swizzle_addr_b(port);
+
+- *(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val);
++ *(volatile __u8 *)(mips_io_port_base + port) = __ioswab8(val);
+ }
+
+ static inline void __outw(unsigned short val, unsigned long port)
+ {
+ port = __swizzle_addr_w(port);
+
+- *(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val);
++ *(volatile __u16 *)(mips_io_port_base + port) = __ioswab16(val);
+ }
+
+ static inline void __outl(unsigned int val, unsigned long port)
+ {
+ port = __swizzle_addr_l(port);
+
+- *(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val);
++ *(volatile __u32 *)(mips_io_port_base + port) = __ioswab32(val);
+ }
+
+ static inline void __outb_p(unsigned char val, unsigned long port)
+ {
+ port = __swizzle_addr_b(port);
+
+- *(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val);
++ *(volatile __u8 *)(mips_io_port_base + port) = __ioswab8(val);
+ SLOW_DOWN_IO;
+ }
+
+@@ -429,7 +429,7 @@
+ {
+ port = __swizzle_addr_w(port);
+
+- *(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val);
++ *(volatile __u16 *)(mips_io_port_base + port) = __ioswab16(val);
+ SLOW_DOWN_IO;
+ }
+
+@@ -437,7 +437,7 @@
+ {
+ port = __swizzle_addr_l(port);
+
+- *(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val);
++ *(volatile __u32 *)(mips_io_port_base + port) = __ioswab32(val);
+ SLOW_DOWN_IO;
+ }
+
+@@ -452,30 +452,30 @@
+ {
+ port = __swizzle_addr_b(port);
+
+- return __ioswab8(*(volatile u8 *)(mips_io_port_base + port));
++ return __ioswab8(*(volatile __u8 *)(mips_io_port_base + port));
+ }
+
+ static inline unsigned short __inw(unsigned long port)
+ {
+ port = __swizzle_addr_w(port);
+
+- return __ioswab16(*(volatile u16 *)(mips_io_port_base + port));
++ return __ioswab16(*(volatile __u16 *)(mips_io_port_base + port));
+ }
+
+ static inline unsigned int __inl(unsigned long port)
+ {
+ port = __swizzle_addr_l(port);
+
+- return __ioswab32(*(volatile u32 *)(mips_io_port_base + port));
++ return __ioswab32(*(volatile __u32 *)(mips_io_port_base + port));
+ }
+
+ static inline unsigned char __inb_p(unsigned long port)
+ {
+- u8 __val;
++ __u8 __val;
+
+ port = __swizzle_addr_b(port);
+
+- __val = *(volatile u8 *)(mips_io_port_base + port);
++ __val = *(volatile __u8 *)(mips_io_port_base + port);
+ SLOW_DOWN_IO;
+
+ return __ioswab8(__val);
+@@ -483,11 +483,11 @@
+
+ static inline unsigned short __inw_p(unsigned long port)
+ {
+- u16 __val;
++ __u16 __val;
+
+ port = __swizzle_addr_w(port);
+
+- __val = *(volatile u16 *)(mips_io_port_base + port);
++ __val = *(volatile __u16 *)(mips_io_port_base + port);
+ SLOW_DOWN_IO;
+
+ return __ioswab16(__val);
+@@ -495,11 +495,11 @@
+
+ static inline unsigned int __inl_p(unsigned long port)
+ {
+- u32 __val;
++ __u32 __val;
+
+ port = __swizzle_addr_l(port);
+
+- __val = *(volatile u32 *)(mips_io_port_base + port);
++ __val = *(volatile __u32 *)(mips_io_port_base + port);
+ SLOW_DOWN_IO;
+
+ return __ioswab32(__val);
+@@ -515,7 +515,7 @@
+ static inline void __outsb(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- outb(*(u8 *)addr, port);
++ outb(*(__u8 *)addr, port);
+ addr++;
+ }
+ }
+@@ -523,7 +523,7 @@
+ static inline void __insb(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- *(u8 *)addr = inb(port);
++ *(__u8 *)addr = inb(port);
+ addr++;
+ }
+ }
+@@ -531,7 +531,7 @@
+ static inline void __outsw(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- outw(*(u16 *)addr, port);
++ outw(*(__u16 *)addr, port);
+ addr += 2;
+ }
+ }
+@@ -539,7 +539,7 @@
+ static inline void __insw(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- *(u16 *)addr = inw(port);
++ *(__u16 *)addr = inw(port);
+ addr += 2;
+ }
+ }
+@@ -547,7 +547,7 @@
+ static inline void __outsl(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- outl(*(u32 *)addr, port);
++ outl(*(__u32 *)addr, port);
+ addr += 4;
+ }
+ }
+@@ -555,7 +555,7 @@
+ static inline void __insl(unsigned long port, void *addr, unsigned int count)
+ {
+ while (count--) {
+- *(u32 *)addr = inl(port);
++ *(__u32 *)addr = inl(port);
+ addr += 4;
+ }
+ }
+@@ -617,7 +617,7 @@
+ #define __CSR_32_ADJUST 0
+ #endif
+
+-#define csr_out32(v,a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v))
+-#define csr_in32(a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST))
++#define csr_out32(v,a) (*(volatile __u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v))
++#define csr_in32(a) (*(volatile __u32 *)((unsigned long)(a) + __CSR_32_ADJUST))
+
+ #endif /* _ASM_IO_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/ip32/mace.h linux-libc-headers-2.6.8.0/include/asm-mips/ip32/mace.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/ip32/mace.h 2004-06-09 07:00:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/ip32/mace.h 2004-08-26 05:14:41.000000000 -0500
+@@ -22,7 +22,7 @@
+ #undef BIT
+ #define BIT(x) (1ULL << (x))
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ typedef struct {
+ volatile unsigned long long reg;
+ } mace64_t;
+@@ -32,7 +32,7 @@
+ volatile unsigned long reg;
+ } mace32_t;
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ typedef struct {
+ volatile unsigned long reg;
+ } mace64_t;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/it8172/it8172.h linux-libc-headers-2.6.8.0/include/asm-mips/it8172/it8172.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/it8172/it8172.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/it8172/it8172.h 2004-08-26 05:22:54.000000000 -0500
+@@ -336,13 +336,13 @@
+ #define TIMER_TIDR 0x0E
+
+
+-#define IT_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs)) = data
+-#define IT_READ(ofs, data) data = *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs))
++#define IT_WRITE(ofs, data) *(volatile __u32 *)KSEG1ADDR((IT8172_BASE+ofs)) = data
++#define IT_READ(ofs, data) data = *(volatile __u32 *)KSEG1ADDR((IT8172_BASE+ofs))
+
+-#define IT_IO_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+-#define IT_IO_READ(ofs, data) data = *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
++#define IT_IO_WRITE(ofs, data) *(volatile __u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
++#define IT_IO_READ(ofs, data) data = *(volatile __u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+-#define IT_IO_WRITE16(ofs, data) *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+-#define IT_IO_READ16(ofs, data) data = *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
++#define IT_IO_WRITE16(ofs, data) *(volatile __u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
++#define IT_IO_READ16(ofs, data) data = *(volatile __u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/lasat/head.h linux-libc-headers-2.6.8.0/include/asm-mips/lasat/head.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/lasat/head.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/lasat/head.h 2004-08-26 05:23:42.000000000 -0500
+@@ -10,12 +10,12 @@
+ #ifndef _LANGUAGE_ASSEMBLY
+ #include <linux/types.h>
+ struct bootloader_header {
+- u32 magic[2];
+- u32 version;
+- u32 image_start;
+- u32 image_size;
+- u32 kernel_start;
+- u32 kernel_entry;
++ __u32 magic[2];
++ __u32 version;
++ __u32 image_start;
++ __u32 image_size;
++ __u32 kernel_start;
++ __u32 kernel_entry;
+ };
+ #endif
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/lasat/lasat.h linux-libc-headers-2.6.8.0/include/asm-mips/lasat/lasat.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/lasat/lasat.h 2004-06-09 07:00:42.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/lasat/lasat.h 2004-08-26 05:23:50.000000000 -0500
+@@ -25,9 +25,9 @@
+ #ifndef _LANGUAGE_ASSEMBLY
+
+ extern struct lasat_misc {
+- volatile u32 *reset_reg;
+- volatile u32 *flash_wp_reg;
+- u32 flash_wp_bit;
++ volatile __u32 *reset_reg;
++ volatile __u32 *flash_wp_reg;
++ __u32 flash_wp_bit;
+ } *lasat_misc;
+
+ enum lasat_mtdparts {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/m48t35.h linux-libc-headers-2.6.8.0/include/asm-mips/m48t35.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/m48t35.h 2004-01-17 17:03:44.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/m48t35.h 2004-08-26 05:23:39.000000000 -0500
+@@ -8,15 +8,15 @@
+ extern spinlock_t rtc_lock;
+
+ struct m48t35_rtc {
+- volatile u8 pad[0x7ff8]; /* starts at 0x7ff8 */
+- volatile u8 control;
+- volatile u8 sec;
+- volatile u8 min;
+- volatile u8 hour;
+- volatile u8 day;
+- volatile u8 date;
+- volatile u8 month;
+- volatile u8 year;
++ volatile __u8 pad[0x7ff8]; /* starts at 0x7ff8 */
++ volatile __u8 control;
++ volatile __u8 sec;
++ volatile __u8 min;
++ volatile __u8 hour;
++ volatile __u8 day;
++ volatile __u8 date;
++ volatile __u8 month;
++ volatile __u8 year;
+ };
+
+ #define M48T35_RTC_SET 0x80
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/bonito64.h linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/bonito64.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/bonito64.h 2004-03-28 07:51:54.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/bonito64.h 2004-08-26 05:21:59.000000000 -0500
+@@ -34,7 +34,7 @@
+ extern unsigned long _pcictrl_bonito;
+ extern unsigned long _pcictrl_bonito_pcicfg;
+
+-#define BONITO(x) *(volatile u32 *)(_pcictrl_bonito + (x))
++#define BONITO(x) *(volatile __u32 *)(_pcictrl_bonito + (x))
+
+ #endif /* __ASSEMBLY__ */
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/generic.h linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/generic.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/generic.h 2004-03-28 07:51:54.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/generic.h 2004-08-26 05:22:06.000000000 -0500
+@@ -74,7 +74,7 @@
+ #define MIPS_REVISION_CORID_CORE_EMUL_BON 0x63
+ #define MIPS_REVISION_CORID_CORE_EMUL_MSC 0x65
+
+-#define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
++#define MIPS_REVISION_CORID (((*(volatile __u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
+
+ extern unsigned int mips_revision_corid;
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/msc01_pci.h linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/msc01_pci.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/mips-boards/msc01_pci.h 2004-03-28 07:51:54.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/mips-boards/msc01_pci.h 2004-08-26 05:22:10.000000000 -0500
+@@ -212,8 +212,8 @@
+
+ #define MSC01_PCI_REG_BASE _pcictrl_msc
+
+-#define MSC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0)
+-#define MSC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0)
++#define MSC_WRITE(reg, data) do { *(volatile __u32 *)(reg) = data; } while (0)
++#define MSC_READ(reg, data) do { data = *(volatile __u32 *)(reg); } while (0)
+
+ /*
+ * Registers absolute addresses
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/mipsregs.h linux-libc-headers-2.6.8.0/include/asm-mips/mipsregs.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/mipsregs.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/mipsregs.h 2004-08-26 13:00:51.000000000 -0500
+@@ -14,7 +14,6 @@
+ #define _ASM_MIPSREGS_H
+
+ #include <linux/linkage.h>
+-#include <asm/hazards.h>
+
+ /*
+ * The following macros are especially useful for __asm__
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/mmu_context.h linux-libc-headers-2.6.8.0/include/asm-mips/mmu_context.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/mmu_context.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/mmu_context.h 2004-08-26 05:14:41.000000000 -0500
+@@ -27,12 +27,12 @@
+ */
+ #define TLBMISS_HANDLER_SETUP_PGD(pgd) \
+ pgd_current[smp_processor_id()] = (unsigned long)(pgd)
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #define TLBMISS_HANDLER_SETUP() \
+ write_c0_context((unsigned long) smp_processor_id() << 23); \
+ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ #define TLBMISS_HANDLER_SETUP() \
+ write_c0_context((unsigned long) &pgd_current[smp_processor_id()] << 23); \
+ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/module.h linux-libc-headers-2.6.8.0/include/asm-mips/module.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/module.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/module.h 2004-08-26 05:14:41.000000000 -0500
+@@ -21,7 +21,7 @@
+ Elf64_Sxword r_addend; /* Addend. */
+ } Elf64_Mips_Rela;
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+@@ -29,7 +29,7 @@
+
+ #endif
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+
+ #define Elf_Shdr Elf64_Shdr
+ #define Elf_Sym Elf64_Sym
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/msgbuf.h linux-libc-headers-2.6.8.0/include/asm-mips/msgbuf.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/msgbuf.h 2004-01-17 17:03:44.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/msgbuf.h 2004-08-26 05:15:04.000000000 -0500
+@@ -14,25 +14,25 @@
+
+ struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused1;
+ #endif
+ __kernel_time_t msg_stime; /* last msgsnd time */
+-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused1;
+ #endif
+-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused2;
+ #endif
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused2;
+ #endif
+-#if defined(CONFIG_MIPS32) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && !defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused3;
+ #endif
+ __kernel_time_t msg_ctime; /* last change time */
+-#if defined(CONFIG_MIPS32) && defined(CONFIG_CPU_LITTLE_ENDIAN)
++#if !defined(__mips64) && defined(CONFIG_CPU_LITTLE_ENDIAN)
+ unsigned long __unused3;
+ #endif
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/nile4.h linux-libc-headers-2.6.8.0/include/asm-mips/nile4.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/nile4.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/nile4.h 2004-08-26 05:22:46.000000000 -0500
+@@ -202,45 +202,45 @@
+
+ static inline void nile4_sync(void)
+ {
+- volatile u32 *p = (volatile u32 *)0xbfc00000;
++ volatile __u32 *p = (volatile __u32 *)0xbfc00000;
+ (void)(*p);
+ }
+
+-static inline void nile4_out32(u32 offset, u32 val)
++static inline void nile4_out32(__u32 offset, __u32 val)
+ {
+- *(volatile u32 *)(NILE4_BASE+offset) = val;
++ *(volatile __u32 *)(NILE4_BASE+offset) = val;
+ nile4_sync();
+ }
+
+-static inline u32 nile4_in32(u32 offset)
++static inline __u32 nile4_in32(__u32 offset)
+ {
+- u32 val = *(volatile u32 *)(NILE4_BASE+offset);
++ __u32 val = *(volatile __u32 *)(NILE4_BASE+offset);
+ nile4_sync();
+ return val;
+ }
+
+-static inline void nile4_out16(u32 offset, u16 val)
++static inline void nile4_out16(__u32 offset, __u16 val)
+ {
+- *(volatile u16 *)(NILE4_BASE+offset) = val;
++ *(volatile __u16 *)(NILE4_BASE+offset) = val;
+ nile4_sync();
+ }
+
+-static inline u16 nile4_in16(u32 offset)
++static inline __u16 nile4_in16(__u32 offset)
+ {
+- u16 val = *(volatile u16 *)(NILE4_BASE+offset);
++ __u16 val = *(volatile __u16 *)(NILE4_BASE+offset);
+ nile4_sync();
+ return val;
+ }
+
+-static inline void nile4_out8(u32 offset, u8 val)
++static inline void nile4_out8(__u32 offset, __u8 val)
+ {
+- *(volatile u8 *)(NILE4_BASE+offset) = val;
++ *(volatile __u8 *)(NILE4_BASE+offset) = val;
+ nile4_sync();
+ }
+
+-static inline u8 nile4_in8(u32 offset)
++static inline __u8 nile4_in8(__u32 offset)
+ {
+- u8 val = *(volatile u8 *)(NILE4_BASE+offset);
++ __u8 val = *(volatile __u8 *)(NILE4_BASE+offset);
+ nile4_sync();
+ return val;
+ }
+@@ -250,7 +250,7 @@
+ * Physical Device Address Registers
+ */
+
+-extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
++extern void nile4_set_pdar(__u32 pdar, __u32 phys, __u32 size, int width,
+ int on_memory_bus, int visible);
+
+
+@@ -276,7 +276,7 @@
+ #define NILE4_PCI_IACK_BASE NILE4_PCI_IO_BASE
+
+
+-extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr);
++extern void nile4_set_pmr(__u32 pmr, __u32 type, __u32 addr);
+
+
+ /*
+@@ -296,14 +296,14 @@
+ extern void nile4_enable_irq(unsigned int nile4_irq);
+ extern void nile4_disable_irq(unsigned int nile4_irq);
+ extern void nile4_disable_irq_all(void);
+-extern u16 nile4_get_irq_stat(int cpu_irq);
++extern __u16 nile4_get_irq_stat(int cpu_irq);
+ extern void nile4_enable_irq_output(int cpu_irq);
+ extern void nile4_disable_irq_output(int cpu_irq);
+ extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
+ extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
+ extern void nile4_clear_irq(int nile4_irq);
+-extern void nile4_clear_irq_mask(u32 mask);
+-extern u8 nile4_i8259_iack(void);
++extern void nile4_clear_irq_mask(__u32 mask);
++extern __u8 nile4_i8259_iack(void);
+ extern void nile4_dump_irq_status(void); /* Debug */
+
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/paccess.h linux-libc-headers-2.6.8.0/include/asm-mips/paccess.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/paccess.h 2004-01-17 17:03:44.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/paccess.h 2004-08-26 05:17:48.000000000 -0500
+@@ -14,11 +14,12 @@
+ #define _ASM_PACCESS_H
+
+ #include <linux/errno.h>
++#include <linux/linkage.h>
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #define __PA_ADDR ".word"
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ #define __PA_ADDR ".dword"
+ #endif
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/pci/bridge.h linux-libc-headers-2.6.8.0/include/asm-mips/pci/bridge.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/pci/bridge.h 2004-03-28 07:51:54.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/pci/bridge.h 2004-08-26 05:25:40.000000000 -0500
+@@ -48,9 +48,9 @@
+ * All accesses to bridge hardware registers must be done
+ * using 32-bit loads and stores.
+ */
+-typedef u32 bridgereg_t;
++typedef __u32 bridgereg_t;
+
+-typedef u64 bridge_ate_t;
++typedef __u64 bridge_ate_t;
+
+ /* pointers to bridge ATEs
+ * are always "pointer to volatile"
+@@ -199,37 +199,37 @@
+
+ /* PCI Device Configuration Spaces 0x020000-0x027FFF */
+ union { /* make all access sizes available. */
+- u8 c[0x1000 / 1];
+- u16 s[0x1000 / 2];
+- u32 l[0x1000 / 4];
+- u64 d[0x1000 / 8];
++ __u8 c[0x1000 / 1];
++ __u16 s[0x1000 / 2];
++ __u32 l[0x1000 / 4];
++ __u64 d[0x1000 / 8];
+ union {
+- u8 c[0x100 / 1];
+- u16 s[0x100 / 2];
+- u32 l[0x100 / 4];
+- u64 d[0x100 / 8];
++ __u8 c[0x100 / 1];
++ __u16 s[0x100 / 2];
++ __u32 l[0x100 / 4];
++ __u64 d[0x100 / 8];
+ } f[8];
+ } b_type0_cfg_dev[8]; /* 0x020000 */
+
+ /* PCI Type 1 Configuration Space 0x028000-0x028FFF */
+ union { /* make all access sizes available. */
+- u8 c[0x1000 / 1];
+- u16 s[0x1000 / 2];
+- u32 l[0x1000 / 4];
+- u64 d[0x1000 / 8];
++ __u8 c[0x1000 / 1];
++ __u16 s[0x1000 / 2];
++ __u32 l[0x1000 / 4];
++ __u64 d[0x1000 / 8];
+ } b_type1_cfg; /* 0x028000-0x029000 */
+
+ char _pad_029000[0x007000]; /* 0x029000-0x030000 */
+
+ /* PCI Interrupt Acknowledge Cycle 0x030000 */
+ union {
+- u8 c[8 / 1];
+- u16 s[8 / 2];
+- u32 l[8 / 4];
+- u64 d[8 / 8];
++ __u8 c[8 / 1];
++ __u16 s[8 / 2];
++ __u32 l[8 / 4];
++ __u64 d[8 / 8];
+ } b_pci_iack; /* 0x030000 */
+
+- u8 _pad_030007[0x04fff8]; /* 0x030008-0x07FFFF */
++ __u8 _pad_030007[0x04fff8]; /* 0x030008-0x07FFFF */
+
+ /* External Address Translation Entry RAM 0x080000-0x0FFFFF */
+ bridge_ate_t b_ext_ate_ram[0x10000];
+@@ -239,10 +239,10 @@
+
+ /* PCI/GIO Device Spaces 0x200000-0xBFFFFF */
+ union { /* make all access sizes available. */
+- u8 c[0x100000 / 1];
+- u16 s[0x100000 / 2];
+- u32 l[0x100000 / 4];
+- u64 d[0x100000 / 8];
++ __u8 c[0x100000 / 1];
++ __u16 s[0x100000 / 2];
++ __u32 l[0x100000 / 4];
++ __u64 d[0x100000 / 8];
+ } b_devio_raw[10]; /* 0x200000 */
+
+ /* b_devio macro is a bit strange; it reflects the
+@@ -253,10 +253,10 @@
+
+ /* External Flash Proms 1,0 0xC00000-0xFFFFFF */
+ union { /* make all access sizes available. */
+- u8 c[0x400000 / 1]; /* read-only */
+- u16 s[0x400000 / 2]; /* read-write */
+- u32 l[0x400000 / 4]; /* read-only */
+- u64 d[0x400000 / 8]; /* read-only */
++ __u8 c[0x400000 / 1]; /* read-only */
++ __u16 s[0x400000 / 2]; /* read-write */
++ __u32 l[0x400000 / 4]; /* read-only */
++ __u64 d[0x400000 / 8]; /* read-only */
+ } b_external_flash; /* 0xC00000 */
+ } bridge_t;
+
+@@ -266,9 +266,9 @@
+ */
+ typedef struct bridge_err_cmdword_s {
+ union {
+- u32 cmd_word;
++ __u32 cmd_word;
+ struct {
+- u32 didn:4, /* Destination ID */
++ __u32 didn:4, /* Destination ID */
+ sidn:4, /* Source ID */
+ pactyp:4, /* Packet type */
+ tnum:5, /* Trans Number */
+@@ -799,17 +799,17 @@
+ #ifndef __ASSEMBLY__
+ /* Address translation entry for mapped pci32 accesses */
+ typedef union ate_u {
+- u64 ent;
++ __u64 ent;
+ struct ate_s {
+- u64 rmf:16;
+- u64 addr:36;
+- u64 targ:4;
+- u64 reserved:3;
+- u64 barrier:1;
+- u64 prefetch:1;
+- u64 precise:1;
+- u64 coherent:1;
+- u64 valid:1;
++ __u64 rmf:16;
++ __u64 addr:36;
++ __u64 targ:4;
++ __u64 reserved:3;
++ __u64 barrier:1;
++ __u64 prefetch:1;
++ __u64 precise:1;
++ __u64 coherent:1;
++ __u64 valid:1;
+ } field;
+ } ate_t;
+ #endif /* !__ASSEMBLY__ */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/pci_channel.h linux-libc-headers-2.6.8.0/include/asm-mips/pci_channel.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/pci_channel.h 2004-03-28 07:51:52.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/pci_channel.h 2004-08-26 05:21:47.000000000 -0500
+@@ -41,6 +41,6 @@
+ /*
+ * board supplied pci irq fixup routine
+ */
+-extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
++extern int pcibios_map_irq(struct pci_dev *dev, __u8 slot, __u8 pin);
+
+ #endif /* __ASM_PCI_CHANNEL_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/pgalloc.h linux-libc-headers-2.6.8.0/include/asm-mips/pgalloc.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/pgalloc.h 2004-06-09 07:00:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/pgalloc.h 2004-08-26 05:14:41.000000000 -0500
+@@ -85,7 +85,7 @@
+
+ #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ #define pgd_populate(mm, pmd, pte) BUG()
+
+ /*
+@@ -97,7 +97,7 @@
+ #define __pmd_free_tlb(tlb,x) do { } while (0)
+ #endif
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+
+ #define pgd_populate(mm, pgd, pmd) set_pgd(pgd, __pgd(pmd))
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/prctl.h linux-libc-headers-2.6.8.0/include/asm-mips/prctl.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/prctl.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/prctl.h 2004-08-26 05:21:43.000000000 -0500
+@@ -12,21 +12,21 @@
+ #define PRDA ((struct prda *) PRDA_ADDRESS)
+
+ struct prda_sys {
+- pid_t t_pid;
+- u32 t_hint;
+- u32 t_dlactseq;
+- u32 t_fpflags;
+- u32 t_prid; /* processor type, $prid CP0 register */
+- u32 t_dlendseq;
+- u64 t_unused1[5];
+- pid_t t_rpid;
+- s32 t_resched;
+- u32 t_unused[8];
+- u32 t_cpu; /* current/last cpu */
++ pid_t t_pid;
++ __u32 t_hint;
++ __u32 t_dlactseq;
++ __u32 t_fpflags;
++ __u32 t_prid; /* processor type, $prid CP0 register */
++ __u32 t_dlendseq;
++ __u64 t_unused1[5];
++ pid_t t_rpid;
++ __s32 t_resched;
++ __u32 t_unused[8];
++ __u32 t_cpu; /* current/last cpu */
+
+ /* FIXME: The signal information, not supported by Linux now */
+- u32 t_flags; /* if true, then the sigprocmask is in userspace */
+- u32 t_sigprocmask [1]; /* the sigprocmask */
++ __u32 t_flags; /* if true, then the sigprocmask is in userspace */
++ __u32 t_sigprocmask [1]; /* the sigprocmask */
+ };
+
+ struct prda {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/processor.h linux-libc-headers-2.6.8.0/include/asm-mips/processor.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/processor.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/processor.h 2004-08-26 05:23:24.000000000 -0500
+@@ -102,7 +102,7 @@
+ #define MCA_bus 0
+ #define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ /*
+ * User space process size: 2GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+@@ -116,7 +116,7 @@
+ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
+ #endif
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ /*
+ * User space process size: 1TB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing. TASK_SIZE
+@@ -142,7 +142,7 @@
+
+ #define NUM_FPU_REGS 32
+
+-typedef u64 fpureg_t;
++typedef __u64 fpureg_t;
+
+ struct mips_fpu_hard_struct {
+ fpureg_t fpr[NUM_FPU_REGS];
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/ptrace.h linux-libc-headers-2.6.8.0/include/asm-mips/ptrace.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/ptrace.h 2004-03-28 07:51:52.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/ptrace.h 2004-08-26 05:14:41.000000000 -0500
+@@ -27,7 +27,7 @@
+ * system call/exception. As usual the registers k0/k1 aren't being saved.
+ */
+ struct pt_regs {
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ /* Pad bytes for argument save space on the stack. */
+ unsigned long pad0[6];
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/serial.h linux-libc-headers-2.6.8.0/include/asm-mips/serial.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/serial.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/serial.h 2004-08-26 13:21:37.000000000 -0500
+@@ -68,7 +68,7 @@
+
+ #define _JAZZ_SERIAL_INIT(int, base) \
+ { .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
+- .iomem_base = (u8 *) base, .iomem_reg_shift = 0, \
++ .iomem_base = (__u8 *) base, .iomem_reg_shift = 0, \
+ .io_type = SERIAL_IO_MEM }
+ #define JAZZ_SERIAL_PORT_DEFNS \
+ _JAZZ_SERIAL_INIT(JAZZ_SERIAL1_IRQ, JAZZ_SERIAL1_BASE), \
+@@ -243,7 +243,7 @@
+ #define _JAGUAR_ATX_SERIAL_INIT(int, base) \
+ { baud_base: JAGUAR_ATX_BASE_BAUD, irq: int, \
+ flags: (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+- iomem_base: (u8 *) base, iomem_reg_shift: 2, \
++ iomem_base: (__u8 *) base, iomem_reg_shift: 2, \
+ io_type: SERIAL_IO_MEM }
+ #define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS \
+ _JAGUAR_ATX_SERIAL_INIT(JAGUAR_ATX_SERIAL1_IRQ, JAGUAR_ATX_SERIAL1_BASE)
+@@ -260,7 +260,7 @@
+
+ #define _OCELOT_SERIAL_INIT(int, base) \
+ { .baud_base = OCELOT_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
+- .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \
++ .iomem_base = (__u8 *) base, .iomem_reg_shift = 2, \
+ .io_type = SERIAL_IO_MEM }
+ #define MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
+ _OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
+@@ -281,7 +281,7 @@
+
+ #define _OCELOT_G_SERIAL_INIT(int, base) \
+ { .baud_base = OCELOT_G_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,\
+- .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \
++ .iomem_base = (__u8 *) base, .iomem_reg_shift = 2, \
+ .io_type = SERIAL_IO_MEM }
+ #define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \
+ _OCELOT_G_SERIAL_INIT(OCELOT_G_SERIAL1_IRQ, OCELOT_G_SERIAL1_BASE)
+@@ -303,7 +303,7 @@
+ { .baud_base = OCELOT_C_BASE_BAUD, \
+ .irq = (int), \
+ .flags = STD_COM_FLAGS, \
+- .iomem_base = (u8 *) base, \
++ .iomem_base = (__u8 *) base, \
+ .iomem_reg_shift = 2, \
+ .io_type = SERIAL_IO_MEM \
+ }
+@@ -318,10 +318,10 @@
+ #include <asm/ddb5xxx/ddb5477.h>
+ #define DDB5477_SERIAL_PORT_DEFNS \
+ { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART0, \
+- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04200, \
++ .flags = STD_COM_FLAGS, .iomem_base = (__u8*)0xbfa04200, \
+ .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM}, \
+ { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART1, \
+- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04240, \
++ .flags = STD_COM_FLAGS, .iomem_base = (__u8*)0xbfa04240, \
+ .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},
+ #else
+ #define DDB5477_SERIAL_PORT_DEFNS
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/hpc3.h linux-libc-headers-2.6.8.0/include/asm-mips/sgi/hpc3.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/hpc3.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sgi/hpc3.h 2004-08-26 05:24:34.000000000 -0500
+@@ -17,8 +17,8 @@
+
+ /* An HPC DMA descriptor. */
+ struct hpc_dma_desc {
+- u32 pbuf; /* physical address of data buffer */
+- u32 cntinfo; /* counter and info bits */
++ __u32 pbuf; /* physical address of data buffer */
++ __u32 cntinfo; /* counter and info bits */
+ #define HPCDMA_EOX 0x80000000 /* last desc in chain for tx */
+ #define HPCDMA_EOR 0x80000000 /* last desc in chain for rx */
+ #define HPCDMA_EOXP 0x40000000 /* end of packet for tx */
+@@ -30,15 +30,15 @@
+ #define HPCDMA_OWN 0x00004000 /* Denotes ring buffer ownership on rx */
+ #define HPCDMA_BCNT 0x00003fff /* size in bytes of this dma buffer */
+
+- u32 pnext; /* paddr of next hpc_dma_desc if any */
++ __u32 pnext; /* paddr of next hpc_dma_desc if any */
+ };
+
+ /* The set of regs for each HPC3 PBUS DMA channel. */
+ struct hpc3_pbus_dmacregs {
+- volatile u32 pbdma_bptr; /* pbus dma channel buffer ptr */
+- volatile u32 pbdma_dptr; /* pbus dma channel desc ptr */
+- u32 _unused0[0x1000/4 - 2]; /* padding */
+- volatile u32 pbdma_ctrl; /* pbus dma channel control register has
++ volatile __u32 pbdma_bptr; /* pbus dma channel buffer ptr */
++ volatile __u32 pbdma_dptr; /* pbus dma channel desc ptr */
++ __u32 _unused0[0x1000/4 - 2]; /* padding */
++ volatile __u32 pbdma_ctrl; /* pbus dma channel control register has
+ * copletely different meaning for read
+ * compared with write */
+ /* read */
+@@ -55,20 +55,20 @@
+ #define HPC3_PDMACTRL_FB 0x003f0000 /* Ptr to beginning of fifo */
+ #define HPC3_PDMACTRL_FE 0x3f000000 /* Ptr to end of fifo */
+
+- u32 _unused1[0x1000/4 - 1]; /* padding */
++ __u32 _unused1[0x1000/4 - 1]; /* padding */
+ };
+
+ /* The HPC3 SCSI registers, this does not include external ones. */
+ struct hpc3_scsiregs {
+- volatile u32 cbptr; /* current dma buffer ptr, diagnostic use only */
+- volatile u32 ndptr; /* next dma descriptor ptr */
+- u32 _unused0[0x1000/4 - 2]; /* padding */
+- volatile u32 bcd; /* byte count info */
++ volatile __u32 cbptr; /* current dma buffer ptr, diagnostic use only */
++ volatile __u32 ndptr; /* next dma descriptor ptr */
++ __u32 _unused0[0x1000/4 - 2]; /* padding */
++ volatile __u32 bcd; /* byte count info */
+ #define HPC3_SBCD_BCNTMSK 0x00003fff /* bytes to transfer from/to memory */
+ #define HPC3_SBCD_XIE 0x00004000 /* Send IRQ when done with cur buf */
+ #define HPC3_SBCD_EOX 0x00008000 /* Indicates this is last buf in chain */
+
+- volatile u32 ctrl; /* control register */
++ volatile __u32 ctrl; /* control register */
+ #define HPC3_SCTRL_IRQ 0x01 /* IRQ asserted, either dma done or parity */
+ #define HPC3_SCTRL_ENDIAN 0x02 /* DMA endian mode, 0=big 1=little */
+ #define HPC3_SCTRL_DIR 0x04 /* DMA direction, 1=dev2mem 0=mem2dev */
+@@ -78,9 +78,9 @@
+ #define HPC3_SCTRL_CRESET 0x40 /* Resets dma channel and external controller */
+ #define HPC3_SCTRL_PERR 0x80 /* Bad parity on HPC3 iface to scsi controller */
+
+- volatile u32 gfptr; /* current GIO fifo ptr */
+- volatile u32 dfptr; /* current device fifo ptr */
+- volatile u32 dconfig; /* DMA configuration register */
++ volatile __u32 gfptr; /* current GIO fifo ptr */
++ volatile __u32 dfptr; /* current device fifo ptr */
++ volatile __u32 dconfig; /* DMA configuration register */
+ #define HPC3_SDCFG_HCLK 0x00001 /* Enable DMA half clock mode */
+ #define HPC3_SDCFG_D1 0x00006 /* Cycles to spend in D1 state */
+ #define HPC3_SDCFG_D2 0x00038 /* Cycles to spend in D2 state */
+@@ -92,7 +92,7 @@
+ #define HPC3_SDCFG_POLL 0x08000 /* hd_dreq polarity control */
+ #define HPC3_SDCFG_ERLY 0x30000 /* hd_dreq behavior control bits */
+
+- volatile u32 pconfig; /* PIO configuration register */
++ volatile __u32 pconfig; /* PIO configuration register */
+ #define HPC3_SPCFG_P3 0x0003 /* Cycles to spend in P3 state */
+ #define HPC3_SPCFG_P2W 0x001c /* Cycles to spend in P2 state for writes */
+ #define HPC3_SPCFG_P2R 0x01e0 /* Cycles to spend in P2 state for reads */
+@@ -102,21 +102,21 @@
+ #define HPC3_SPCFG_EPAR 0x4000 /* Enable parity checking for PIO */
+ #define HPC3_SPCFG_FUJI 0x8000 /* Fujitsu scsi controller mode for faster dma/pio */
+
+- u32 _unused1[0x1000/4 - 6]; /* padding */
++ __u32 _unused1[0x1000/4 - 6]; /* padding */
+ };
+
+ /* SEEQ ethernet HPC3 registers, only one seeq per HPC3. */
+ struct hpc3_ethregs {
+ /* Receiver registers. */
+- volatile u32 rx_cbptr; /* current dma buffer ptr, diagnostic use only */
+- volatile u32 rx_ndptr; /* next dma descriptor ptr */
+- u32 _unused0[0x1000/4 - 2]; /* padding */
+- volatile u32 rx_bcd; /* byte count info */
++ volatile __u32 rx_cbptr; /* current dma buffer ptr, diagnostic use only */
++ volatile __u32 rx_ndptr; /* next dma descriptor ptr */
++ __u32 _unused0[0x1000/4 - 2]; /* padding */
++ volatile __u32 rx_bcd; /* byte count info */
+ #define HPC3_ERXBCD_BCNTMSK 0x00003fff /* bytes to be sent to memory */
+ #define HPC3_ERXBCD_XIE 0x20000000 /* HPC3 interrupts cpu at end of this buf */
+ #define HPC3_ERXBCD_EOX 0x80000000 /* flags this as end of descriptor chain */
+
+- volatile u32 rx_ctrl; /* control register */
++ volatile __u32 rx_ctrl; /* control register */
+ #define HPC3_ERXCTRL_STAT50 0x0000003f /* Receive status reg bits of Seeq8003 */
+ #define HPC3_ERXCTRL_STAT6 0x00000040 /* Rdonly irq status */
+ #define HPC3_ERXCTRL_STAT7 0x00000080 /* Rdonlt old/new status bit from Seeq */
+@@ -125,15 +125,15 @@
+ #define HPC3_ERXCTRL_AMASK 0x00000400 /* Tells if ACTIVE inhibits PIO's to hpc3 */
+ #define HPC3_ERXCTRL_RBO 0x00000800 /* Receive buffer overflow if set to 1 */
+
+- volatile u32 rx_gfptr; /* current GIO fifo ptr */
+- volatile u32 rx_dfptr; /* current device fifo ptr */
+- u32 _unused1; /* padding */
+- volatile u32 rx_reset; /* reset register */
++ volatile __u32 rx_gfptr; /* current GIO fifo ptr */
++ volatile __u32 rx_dfptr; /* current device fifo ptr */
++ __u32 _unused1; /* padding */
++ volatile __u32 rx_reset; /* reset register */
+ #define HPC3_ERXRST_CRESET 0x1 /* Reset dma channel and external controller */
+ #define HPC3_ERXRST_CLRIRQ 0x2 /* Clear channel interrupt */
+ #define HPC3_ERXRST_LBACK 0x4 /* Enable diagnostic loopback mode of Seeq8003 */
+
+- volatile u32 rx_dconfig; /* DMA configuration register */
++ volatile __u32 rx_dconfig; /* DMA configuration register */
+ #define HPC3_ERXDCFG_D1 0x0000f /* Cycles to spend in D1 state for PIO */
+ #define HPC3_ERXDCFG_D2 0x000f0 /* Cycles to spend in D2 state for PIO */
+ #define HPC3_ERXDCFG_D3 0x00f00 /* Cycles to spend in D3 state for PIO */
+@@ -143,26 +143,26 @@
+ #define HPC3_ERXDCFG_FIRQ 0x08000 /* Another bad packet timeout enable */
+ #define HPC3_ERXDCFG_PTO 0x30000 /* Programmed timeout value for above two */
+
+- volatile u32 rx_pconfig; /* PIO configuration register */
++ volatile __u32 rx_pconfig; /* PIO configuration register */
+ #define HPC3_ERXPCFG_P1 0x000f /* Cycles to spend in P1 state for PIO */
+ #define HPC3_ERXPCFG_P2 0x00f0 /* Cycles to spend in P2 state for PIO */
+ #define HPC3_ERXPCFG_P3 0x0f00 /* Cycles to spend in P3 state for PIO */
+ #define HPC3_ERXPCFG_TST 0x1000 /* Diagnistic ram test feature bit */
+
+- u32 _unused2[0x1000/4 - 8]; /* padding */
++ __u32 _unused2[0x1000/4 - 8]; /* padding */
+
+ /* Transmitter registers. */
+- volatile u32 tx_cbptr; /* current dma buffer ptr, diagnostic use only */
+- volatile u32 tx_ndptr; /* next dma descriptor ptr */
+- u32 _unused3[0x1000/4 - 2]; /* padding */
+- volatile u32 tx_bcd; /* byte count info */
++ volatile __u32 tx_cbptr; /* current dma buffer ptr, diagnostic use only */
++ volatile __u32 tx_ndptr; /* next dma descriptor ptr */
++ __u32 _unused3[0x1000/4 - 2]; /* padding */
++ volatile __u32 tx_bcd; /* byte count info */
+ #define HPC3_ETXBCD_BCNTMSK 0x00003fff /* bytes to be read from memory */
+ #define HPC3_ETXBCD_ESAMP 0x10000000 /* if set, too late to add descriptor */
+ #define HPC3_ETXBCD_XIE 0x20000000 /* Interrupt cpu at end of cur desc */
+ #define HPC3_ETXBCD_EOP 0x40000000 /* Last byte of cur buf is end of packet */
+ #define HPC3_ETXBCD_EOX 0x80000000 /* This buf is the end of desc chain */
+
+- volatile u32 tx_ctrl; /* control register */
++ volatile __u32 tx_ctrl; /* control register */
+ #define HPC3_ETXCTRL_STAT30 0x0000000f /* Rdonly copy of seeq tx stat reg */
+ #define HPC3_ETXCTRL_STAT4 0x00000010 /* Indicate late collision occurred */
+ #define HPC3_ETXCTRL_STAT75 0x000000e0 /* Rdonly irq status from seeq */
+@@ -170,9 +170,9 @@
+ #define HPC3_ETXCTRL_ACTIVE 0x00000200 /* DMA tx channel is active */
+ #define HPC3_ETXCTRL_AMASK 0x00000400 /* Indicates ACTIVE inhibits PIO's */
+
+- volatile u32 tx_gfptr; /* current GIO fifo ptr */
+- volatile u32 tx_dfptr; /* current device fifo ptr */
+- u32 _unused4[0x1000/4 - 4]; /* padding */
++ volatile __u32 tx_gfptr; /* current GIO fifo ptr */
++ volatile __u32 tx_dfptr; /* current device fifo ptr */
++ __u32 _unused4[0x1000/4 - 4]; /* padding */
+ };
+
+ struct hpc3_regs {
+@@ -188,7 +188,7 @@
+ /* Here are where the hpc3 fifo's can be directly accessed
+ * via PIO accesses. Under normal operation we never stick
+ * our grubby paws in here so it's just padding. */
+- u32 _unused0[0x18000/4];
++ __u32 _unused0[0x18000/4];
+
+ /* HPC3 irq status regs. Due to a peculiar bug you need to
+ * look at two different register addresses to get at all of
+@@ -197,42 +197,42 @@
+ * reliably report bits 9:5 of the hpc3 irq status. I told
+ * you it was a peculiar bug. ;-)
+ */
+- volatile u32 istat0; /* Irq status, only bits <4:0> reliable. */
++ volatile __u32 istat0; /* Irq status, only bits <4:0> reliable. */
+ #define HPC3_ISTAT_PBIMASK 0x0ff /* irq bits for pbus devs 0 --> 7 */
+ #define HPC3_ISTAT_SC0MASK 0x100 /* irq bit for scsi channel 0 */
+ #define HPC3_ISTAT_SC1MASK 0x200 /* irq bit for scsi channel 1 */
+
+- volatile u32 gio_misc; /* GIO misc control bits. */
++ volatile __u32 gio_misc; /* GIO misc control bits. */
+ #define HPC3_GIOMISC_ERTIME 0x1 /* Enable external timer real time. */
+ #define HPC3_GIOMISC_DENDIAN 0x2 /* dma descriptor endian, 1=lit 0=big */
+
+- volatile u32 eeprom; /* EEPROM data reg. */
++ volatile __u32 eeprom; /* EEPROM data reg. */
+ #define HPC3_EEPROM_EPROT 0x01 /* Protect register enable */
+ #define HPC3_EEPROM_CSEL 0x02 /* Chip select */
+ #define HPC3_EEPROM_ECLK 0x04 /* EEPROM clock */
+ #define HPC3_EEPROM_DATO 0x08 /* Data out */
+ #define HPC3_EEPROM_DATI 0x10 /* Data in */
+
+- volatile u32 istat1; /* Irq status, only bits <9:5> reliable. */
+- volatile u32 bestat; /* Bus error interrupt status reg. */
++ volatile __u32 istat1; /* Irq status, only bits <9:5> reliable. */
++ volatile __u32 bestat; /* Bus error interrupt status reg. */
+ #define HPC3_BESTAT_BLMASK 0x000ff /* Bus lane where bad parity occurred */
+ #define HPC3_BESTAT_CTYPE 0x00100 /* Bus cycle type, 0=PIO 1=DMA */
+ #define HPC3_BESTAT_PIDSHIFT 9
+ #define HPC3_BESTAT_PIDMASK 0x3f700 /* DMA channel parity identifier */
+
+- u32 _unused1[0x14000/4 - 5]; /* padding */
++ __u32 _unused1[0x14000/4 - 5]; /* padding */
+
+ /* Now direct PIO per-HPC3 peripheral access to external regs. */
+- volatile u32 scsi0_ext[256]; /* SCSI channel 0 external regs */
+- u32 _unused2[0x7c00/4];
+- volatile u32 scsi1_ext[256]; /* SCSI channel 1 external regs */
+- u32 _unused3[0x7c00/4];
+- volatile u32 eth_ext[320]; /* Ethernet external registers */
+- u32 _unused4[0x3b00/4];
++ volatile __u32 scsi0_ext[256]; /* SCSI channel 0 external regs */
++ __u32 _unused2[0x7c00/4];
++ volatile __u32 scsi1_ext[256]; /* SCSI channel 1 external regs */
++ __u32 _unused3[0x7c00/4];
++ volatile __u32 eth_ext[320]; /* Ethernet external registers */
++ __u32 _unused4[0x3b00/4];
+
+ /* Per-peripheral device external registers and DMA/PIO control. */
+- volatile u32 pbus_extregs[16][256];
+- volatile u32 pbus_dmacfg[8][128];
++ volatile __u32 pbus_extregs[16][256];
++ volatile __u32 pbus_dmacfg[8][128];
+ /* Cycles to spend in D3 for reads */
+ #define HPC3_DMACFG_D3R_MASK 0x00000001
+ #define HPC3_DMACFG_D3R_SHIFT 0
+@@ -262,7 +262,7 @@
+ #define HPC3_DMACFG_BURST_SHIFT 22
+ /* Use live pbus_dreq unsynchronized signal */
+ #define HPC3_DMACFG_DRQLIVE 0x08000000
+- volatile u32 pbus_piocfg[16][64];
++ volatile __u32 pbus_piocfg[16][64];
+ /* Cycles to spend in P2 state for reads */
+ #define HPC3_PIOCFG_P2R_MASK 0x00001
+ #define HPC3_PIOCFG_P2R_SHIFT 0
+@@ -287,21 +287,21 @@
+ #define HPC3_PIOCFG_EVENHI 0x80000
+
+ /* PBUS PROM control regs. */
+- volatile u32 pbus_promwe; /* PROM write enable register */
++ volatile __u32 pbus_promwe; /* PROM write enable register */
+ #define HPC3_PROM_WENAB 0x1 /* Enable writes to the PROM */
+
+- u32 _unused5[0x0800/4 - 1];
+- volatile u32 pbus_promswap; /* Chip select swap reg */
++ __u32 _unused5[0x0800/4 - 1];
++ volatile __u32 pbus_promswap; /* Chip select swap reg */
+ #define HPC3_PROM_SWAP 0x1 /* invert GIO addr bit to select prom0 or prom1 */
+
+- u32 _unused6[0x0800/4 - 1];
+- volatile u32 pbus_gout; /* PROM general purpose output reg */
++ __u32 _unused6[0x0800/4 - 1];
++ volatile __u32 pbus_gout; /* PROM general purpose output reg */
+ #define HPC3_PROM_STAT 0x1 /* General purpose status bit in gout */
+
+- u32 _unused7[0x1000/4 - 1];
+- volatile u32 rtcregs[14]; /* Dallas clock registers */
+- u32 _unused8[50];
+- volatile u32 bbram[8192-50-14]; /* Battery backed ram */
++ __u32 _unused7[0x1000/4 - 1];
++ volatile __u32 rtcregs[14]; /* Dallas clock registers */
++ __u32 _unused8[50];
++ volatile __u32 bbram[8192-50-14]; /* Battery backed ram */
+ };
+
+ /*
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/ioc.h linux-libc-headers-2.6.8.0/include/asm-mips/sgi/ioc.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/ioc.h 2004-03-28 07:51:54.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sgi/ioc.h 2004-08-26 05:24:48.000000000 -0500
+@@ -22,26 +22,26 @@
+ */
+
+ struct sgioc_uart_regs {
+- u8 _ctrl1[3];
+- volatile u8 ctrl1;
+- u8 _data1[3];
+- volatile u8 data1;
+- u8 _ctrl2[3];
+- volatile u8 ctrl2;
+- u8 _data2[3];
+- volatile u8 data2;
++ __u8 _ctrl1[3];
++ volatile __u8 ctrl1;
++ __u8 _data1[3];
++ volatile __u8 data1;
++ __u8 _ctrl2[3];
++ volatile __u8 ctrl2;
++ __u8 _data2[3];
++ volatile __u8 data2;
+ };
+
+ struct sgioc_keyb_regs {
+- u8 _data[3];
+- volatile u8 data;
+- u8 _command[3];
+- volatile u8 command;
++ __u8 _data[3];
++ volatile __u8 data;
++ __u8 _command[3];
++ volatile __u8 command;
+ };
+
+ struct sgint_regs {
+- u8 _istat0[3];
+- volatile u8 istat0; /* Interrupt status zero */
++ __u8 _istat0[3];
++ volatile __u8 istat0; /* Interrupt status zero */
+ #define SGINT_ISTAT0_FFULL 0x01
+ #define SGINT_ISTAT0_SCSI0 0x02
+ #define SGINT_ISTAT0_SCSI1 0x04
+@@ -50,10 +50,10 @@
+ #define SGINT_ISTAT0_PPORT 0x20
+ #define SGINT_ISTAT0_HPC2 0x40
+ #define SGINT_ISTAT0_LIO2 0x80
+- u8 _imask0[3];
+- volatile u8 imask0; /* Interrupt mask zero */
+- u8 _istat1[3];
+- volatile u8 istat1; /* Interrupt status one */
++ __u8 _imask0[3];
++ volatile __u8 imask0; /* Interrupt mask zero */
++ __u8 _istat1[3];
++ volatile __u8 istat1; /* Interrupt status one */
+ #define SGINT_ISTAT1_ISDNI 0x01
+ #define SGINT_ISTAT1_PWR 0x02
+ #define SGINT_ISTAT1_ISDNH 0x04
+@@ -62,29 +62,29 @@
+ #define SGINT_ISTAT1_AFAIL 0x20
+ #define SGINT_ISTAT1_VIDEO 0x40
+ #define SGINT_ISTAT1_GIO2 0x80
+- u8 _imask1[3];
+- volatile u8 imask1; /* Interrupt mask one */
+- u8 _vmeistat[3];
+- volatile u8 vmeistat; /* VME interrupt status */
+- u8 _cmeimask0[3];
+- volatile u8 cmeimask0; /* VME interrupt mask zero */
+- u8 _cmeimask1[3];
+- volatile u8 cmeimask1; /* VME interrupt mask one */
+- u8 _cmepol[3];
+- volatile u8 cmepol; /* VME polarity */
+- u8 _tclear[3];
+- volatile u8 tclear;
+- u8 _errstat[3];
+- volatile u8 errstat; /* Error status reg, reserved on INT2 */
+- u32 _unused0[2];
+- u8 _tcnt0[3];
+- volatile u8 tcnt0; /* counter 0 */
+- u8 _tcnt1[3];
+- volatile u8 tcnt1; /* counter 1 */
+- u8 _tcnt2[3];
+- volatile u8 tcnt2; /* counter 2 */
+- u8 _tcword[3];
+- volatile u8 tcword; /* control word */
++ __u8 _imask1[3];
++ volatile __u8 imask1; /* Interrupt mask one */
++ __u8 _vmeistat[3];
++ volatile __u8 vmeistat; /* VME interrupt status */
++ __u8 _cmeimask0[3];
++ volatile __u8 cmeimask0; /* VME interrupt mask zero */
++ __u8 _cmeimask1[3];
++ volatile __u8 cmeimask1; /* VME interrupt mask one */
++ __u8 _cmepol[3];
++ volatile __u8 cmepol; /* VME polarity */
++ __u8 _tclear[3];
++ volatile __u8 tclear;
++ __u8 _errstat[3];
++ volatile __u8 errstat; /* Error status reg, reserved on INT2 */
++ __u32 _unused0[2];
++ __u8 _tcnt0[3];
++ volatile __u8 tcnt0; /* counter 0 */
++ __u8 _tcnt1[3];
++ volatile __u8 tcnt1; /* counter 1 */
++ __u8 _tcnt2[3];
++ volatile __u8 tcnt2; /* counter 2 */
++ __u8 _tcword[3];
++ volatile __u8 tcword; /* control word */
+ #define SGINT_TCWORD_BCD 0x01 /* Use BCD mode for counters */
+ #define SGINT_TCWORD_MMASK 0x0e /* Mode bitmask. */
+ #define SGINT_TCWORD_MITC 0x00 /* IRQ on terminal count (doesn't work) */
+@@ -115,55 +115,55 @@
+ #define SGINT_TCSAMP_COUNTER ((SGINT_TIMER_CLOCK / HZ) + 255)
+
+ /* We need software copies of these because they are write only. */
+-extern u8 sgi_ioc_reset, sgi_ioc_write;
++extern __u8 sgi_ioc_reset, sgi_ioc_write;
+
+ struct sgioc_regs {
+ struct pi1_regs pport;
+- u32 _unused0[2];
++ __u32 _unused0[2];
+ struct sgioc_uart_regs serport;
+ struct sgioc_keyb_regs kbdmouse;
+- u8 _gcsel[3];
+- volatile u8 gcsel;
+- u8 _genctrl[3];
+- volatile u8 genctrl;
+- u8 _panel[3];
+- volatile u8 panel;
++ __u8 _gcsel[3];
++ volatile __u8 gcsel;
++ __u8 _genctrl[3];
++ volatile __u8 genctrl;
++ __u8 _panel[3];
++ volatile __u8 panel;
+ #define SGIOC_PANEL_POWERON 0x01
+ #define SGIOC_PANEL_POWERINTR 0x02
+ #define SGIOC_PANEL_VOLDNINTR 0x10
+ #define SGIOC_PANEL_VOLDNHOLD 0x20
+ #define SGIOC_PANEL_VOLUPINTR 0x40
+ #define SGIOC_PANEL_VOLUPHOLD 0x80
+- u32 _unused1;
+- u8 _sysid[3];
+- volatile u8 sysid;
++ __u32 _unused1;
++ __u8 _sysid[3];
++ volatile __u8 sysid;
+ #define SGIOC_SYSID_FULLHOUSE 0x01
+ #define SGIOC_SYSID_BOARDREV(x) ((x & 0xe0) > 5)
+ #define SGIOC_SYSID_CHIPREV(x) ((x & 0x1e) > 1)
+- u32 _unused2;
+- u8 _read[3];
+- volatile u8 read;
+- u32 _unused3;
+- u8 _dmasel[3];
+- volatile u8 dmasel;
++ __u32 _unused2;
++ __u8 _read[3];
++ volatile __u8 read;
++ __u32 _unused3;
++ __u8 _dmasel[3];
++ volatile __u8 dmasel;
+ #define SGIOC_DMASEL_SCLK10MHZ 0x00 /* use 10MHZ serial clock */
+ #define SGIOC_DMASEL_ISDNB 0x01 /* enable isdn B */
+ #define SGIOC_DMASEL_ISDNA 0x02 /* enable isdn A */
+ #define SGIOC_DMASEL_PPORT 0x04 /* use parallel DMA */
+ #define SGIOC_DMASEL_SCLK667MHZ 0x10 /* use 6.67MHZ serial clock */
+ #define SGIOC_DMASEL_SCLKEXT 0x20 /* use external serial clock */
+- u32 _unused4;
+- u8 _reset[3];
+- volatile u8 reset;
++ __u32 _unused4;
++ __u8 _reset[3];
++ volatile __u8 reset;
+ #define SGIOC_RESET_PPORT 0x01 /* 0=parport reset, 1=nornal */
+ #define SGIOC_RESET_KBDMOUSE 0x02 /* 0=kbdmouse reset, 1=normal */
+ #define SGIOC_RESET_EISA 0x04 /* 0=eisa reset, 1=normal */
+ #define SGIOC_RESET_ISDN 0x08 /* 0=isdn reset, 1=normal */
+ #define SGIOC_RESET_LC0OFF 0x10 /* guiness: turn led off (red, else green) */
+ #define SGIOC_RESET_LC1OFF 0x20 /* guiness: turn led off (green, else amber) */
+- u32 _unused5;
+- u8 _write[3];
+- volatile u8 write;
++ __u32 _unused5;
++ __u8 _write[3];
++ volatile __u8 write;
+ #define SGIOC_WRITE_NTHRESH 0x01 /* use 4.5db threshhold */
+ #define SGIOC_WRITE_TPSPEED 0x02 /* use 100ohm TP speed */
+ #define SGIOC_WRITE_EPSEL 0x04 /* force cable mode: 1=AUI 0=TP */
+@@ -172,10 +172,10 @@
+ #define SGIOC_WRITE_U0AMODE 0x20 /* 1=PC 0=MAC UART mode */
+ #define SGIOC_WRITE_MLO 0x40 /* 1=4.75V 0=+5V */
+ #define SGIOC_WRITE_MHI 0x80 /* 1=5.25V 0=+5V */
+- u32 _unused6;
++ __u32 _unused6;
+ struct sgint_regs int3;
+- u32 _unused7[16];
+- volatile u32 extio; /* FullHouse only */
++ __u32 _unused7[16];
++ volatile __u32 extio; /* FullHouse only */
+ #define EXTIO_S0_IRQ_3 0x8000 /* S0: vid.vsync */
+ #define EXTIO_S0_IRQ_2 0x4000 /* S0: gfx.fifofull */
+ #define EXTIO_S0_IRQ_1 0x2000 /* S0: gfx.int */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/mc.h linux-libc-headers-2.6.8.0/include/asm-mips/sgi/mc.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgi/mc.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sgi/mc.h 2004-08-26 05:25:28.000000000 -0500
+@@ -14,8 +14,8 @@
+ #define _SGI_MC_H
+
+ struct sgimc_regs {
+- u32 _unused0;
+- volatile u32 cpuctrl0; /* CPU control register 0, readwrite */
++ __u32 _unused0;
++ volatile __u32 cpuctrl0; /* CPU control register 0, readwrite */
+ #define SGIMC_CCTRL0_REFS 0x0000000f /* REFS mask */
+ #define SGIMC_CCTRL0_EREFRESH 0x00000010 /* Memory refresh enable */
+ #define SGIMC_CCTRL0_EPERRGIO 0x00000020 /* GIO parity error enable */
+@@ -35,8 +35,8 @@
+ #define SGIMC_CCTRL0_CMEMBADPAR 0x02000000 /* Generate bad perr from cpu to mem */
+ #define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */
+ #define SGIMC_CCTRL0_GIOBTOB 0x08000000 /* Allow GIO back to back writes */
+- u32 _unused1;
+- volatile u32 cpuctrl1; /* CPU control register 1, readwrite */
++ __u32 _unused1;
++ volatile __u32 cpuctrl1; /* CPU control register 1, readwrite */
+ #define SGIMC_CCTRL1_EGIOTIMEO 0x00000010 /* GIO bus timeout enable */
+ #define SGIMC_CCTRL1_FIXEDEHPC 0x00001000 /* Fixed HPC endianness */
+ #define SGIMC_CCTRL1_LITTLEHPC 0x00002000 /* Little endian HPC */
+@@ -45,33 +45,33 @@
+ #define SGIMC_CCTRL1_FIXEDEEXP1 0x00010000 /* Fixed EXP1 endianness */
+ #define SGIMC_CCTRL1_LITTLEEXP1 0x00020000 /* Little endian EXP1 */
+
+- u32 _unused2;
+- volatile u32 watchdogt; /* Watchdog reg rdonly, write clears */
++ __u32 _unused2;
++ volatile __u32 watchdogt; /* Watchdog reg rdonly, write clears */
+
+- u32 _unused3;
+- volatile u32 systemid; /* MC system ID register, readonly */
++ __u32 _unused3;
++ volatile __u32 systemid; /* MC system ID register, readonly */
+ #define SGIMC_SYSID_MASKREV 0x0000000f /* Revision of MC controller */
+ #define SGIMC_SYSID_EPRESENT 0x00000010 /* Indicates presence of EISA bus */
+
+- u32 _unused4[3];
+- volatile u32 divider; /* Divider reg for RPSS */
++ __u32 _unused4[3];
++ volatile __u32 divider; /* Divider reg for RPSS */
+
+- u32 _unused5;
+- volatile u32 eeprom; /* EEPROM byte reg for r4k */
++ __u32 _unused5;
++ volatile __u32 eeprom; /* EEPROM byte reg for r4k */
+ #define SGIMC_EEPROM_PRE 0x00000001 /* eeprom chip PRE pin assertion */
+ #define SGIMC_EEPROM_CSEL 0x00000002 /* Active high, eeprom chip select */
+ #define SGIMC_EEPROM_SECLOCK 0x00000004 /* EEPROM serial clock */
+ #define SGIMC_EEPROM_SDATAO 0x00000008 /* Serial EEPROM data-out */
+ #define SGIMC_EEPROM_SDATAI 0x00000010 /* Serial EEPROM data-in */
+
+- u32 _unused6[3];
+- volatile u32 rcntpre; /* Preload refresh counter */
++ __u32 _unused6[3];
++ volatile __u32 rcntpre; /* Preload refresh counter */
+
+- u32 _unused7;
+- volatile u32 rcounter; /* Readonly refresh counter */
++ __u32 _unused7;
++ volatile __u32 rcounter; /* Readonly refresh counter */
+
+- u32 _unused8[13];
+- volatile u32 giopar; /* Parameter word for GIO64 */
++ __u32 _unused8[13];
++ volatile __u32 giopar; /* Parameter word for GIO64 */
+ #define SGIMC_GIOPAR_HPC64 0x00000001 /* HPC talks to GIO using 64-bits */
+ #define SGIMC_GIOPAR_GFX64 0x00000002 /* GFX talks to GIO using 64-bits */
+ #define SGIMC_GIOPAR_EXP064 0x00000004 /* EXP(slot0) talks using 64-bits */
+@@ -89,36 +89,36 @@
+ #define SGIMC_GIOPAR_PLINEEXP0 0x00004000 /* EXP(slot0) has pipeline attr */
+ #define SGIMC_GIOPAR_PLINEEXP1 0x00008000 /* EXP(slot1) has pipeline attr */
+
+- u32 _unused9;
+- volatile u32 cputp; /* CPU bus arb time period */
++ __u32 _unused9;
++ volatile __u32 cputp; /* CPU bus arb time period */
+
+- u32 _unused10[3];
+- volatile u32 lbursttp; /* Time period for long bursts */
++ __u32 _unused10[3];
++ volatile __u32 lbursttp; /* Time period for long bursts */
+
+ /* MC chip can drive up to 4 bank 4 SIMMs each. All SIMMs in bank must
+ * be the same size. The size encoding for supported SIMMs is bellow */
+- u32 _unused11[9];
+- volatile u32 mconfig0; /* Memory config register zero */
+- u32 _unused12;
+- volatile u32 mconfig1; /* Memory config register one */
++ __u32 _unused11[9];
++ volatile __u32 mconfig0; /* Memory config register zero */
++ __u32 _unused12;
++ volatile __u32 mconfig1; /* Memory config register one */
+ #define SGIMC_MCONFIG_BASEADDR 0x000000ff /* Base address of bank*/
+ #define SGIMC_MCONFIG_RMASK 0x00001f00 /* Ram config bitmask */
+ #define SGIMC_MCONFIG_BVALID 0x00002000 /* Bank is valid */
+ #define SGIMC_MCONFIG_SBANKS 0x00004000 /* Number of subbanks */
+
+- u32 _unused13;
+- volatile u32 cmacc; /* Mem access config for CPU */
+- u32 _unused14;
+- volatile u32 gmacc; /* Mem access config for GIO */
++ __u32 _unused13;
++ volatile __u32 cmacc; /* Mem access config for CPU */
++ __u32 _unused14;
++ volatile __u32 gmacc; /* Mem access config for GIO */
+
+ /* This define applies to both cmacc and gmacc registers above. */
+ #define SGIMC_MACC_ALIASBIG 0x20000000 /* 512MB home for alias */
+
+ /* Error address/status regs from GIO and CPU perspectives. */
+- u32 _unused15;
+- volatile u32 cerr; /* Error address reg for CPU */
+- u32 _unused16;
+- volatile u32 cstat; /* Status reg for CPU */
++ __u32 _unused15;
++ volatile __u32 cerr; /* Error address reg for CPU */
++ __u32 _unused16;
++ volatile __u32 cstat; /* Status reg for CPU */
+ #define SGIMC_CSTAT_RD 0x00000100 /* read parity error */
+ #define SGIMC_CSTAT_PAR 0x00000200 /* CPU parity error */
+ #define SGIMC_CSTAT_ADDR 0x00000400 /* memory bus error bad addr */
+@@ -128,10 +128,10 @@
+ #define SGIMC_CSTAT_PAR_MASK 0x00001f00 /* parity error mask */
+ #define SGIMC_CSTAT_RD_PAR (SGIMC_CSTAT_RD | SGIMC_CSTAT_PAR)
+
+- u32 _unused17;
+- volatile u32 gerr; /* Error address reg for GIO */
+- u32 _unused18;
+- volatile u32 gstat; /* Status reg for GIO */
++ __u32 _unused17;
++ volatile __u32 gerr; /* Error address reg for GIO */
++ __u32 _unused18;
++ volatile __u32 gstat; /* Status reg for GIO */
+ #define SGIMC_GSTAT_RD 0x00000100 /* read parity error */
+ #define SGIMC_GSTAT_WR 0x00000200 /* write parity error */
+ #define SGIMC_GSTAT_TIME 0x00000400 /* GIO bus timed out */
+@@ -142,76 +142,76 @@
+ #define SGIMC_GSTAT_PIO_WR 0x00008000 /* write data parity on pio */
+
+ /* Special hard bus locking registers. */
+- u32 _unused19;
+- volatile u32 syssembit; /* Uni-bit system semaphore */
+- u32 _unused20;
+- volatile u32 mlock; /* Global GIO memory access lock */
+- u32 _unused21;
+- volatile u32 elock; /* Locks EISA from GIO accesses */
++ __u32 _unused19;
++ volatile __u32 syssembit; /* Uni-bit system semaphore */
++ __u32 _unused20;
++ volatile __u32 mlock; /* Global GIO memory access lock */
++ __u32 _unused21;
++ volatile __u32 elock; /* Locks EISA from GIO accesses */
+
+ /* GIO dma control registers. */
+- u32 _unused22[15];
+- volatile u32 gio_dma_trans; /* DMA mask to translation GIO addrs */
+- u32 _unused23;
+- volatile u32 gio_dma_sbits; /* DMA GIO addr substitution bits */
+- u32 _unused24;
+- volatile u32 dma_intr_cause; /* DMA IRQ cause indicator bits */
+- u32 _unused25;
+- volatile u32 dma_ctrl; /* Main DMA control reg */
++ __u32 _unused22[15];
++ volatile __u32 gio_dma_trans; /* DMA mask to translation GIO addrs */
++ __u32 _unused23;
++ volatile __u32 gio_dma_sbits; /* DMA GIO addr substitution bits */
++ __u32 _unused24;
++ volatile __u32 dma_intr_cause; /* DMA IRQ cause indicator bits */
++ __u32 _unused25;
++ volatile __u32 dma_ctrl; /* Main DMA control reg */
+
+ /* DMA TLB entry 0 */
+- u32 _unused26[5];
+- volatile u32 dtlb_hi0;
+- u32 _unused27;
+- volatile u32 dtlb_lo0;
++ __u32 _unused26[5];
++ volatile __u32 dtlb_hi0;
++ __u32 _unused27;
++ volatile __u32 dtlb_lo0;
+
+ /* DMA TLB entry 1 */
+- u32 _unused28;
+- volatile u32 dtlb_hi1;
+- u32 _unused29;
+- volatile u32 dtlb_lo1;
++ __u32 _unused28;
++ volatile __u32 dtlb_hi1;
++ __u32 _unused29;
++ volatile __u32 dtlb_lo1;
+
+ /* DMA TLB entry 2 */
+- u32 _unused30;
+- volatile u32 dtlb_hi2;
+- u32 _unused31;
+- volatile u32 dtlb_lo2;
++ __u32 _unused30;
++ volatile __u32 dtlb_hi2;
++ __u32 _unused31;
++ volatile __u32 dtlb_lo2;
+
+ /* DMA TLB entry 3 */
+- u32 _unused32;
+- volatile u32 dtlb_hi3;
+- u32 _unused33;
+- volatile u32 dtlb_lo3;
++ __u32 _unused32;
++ volatile __u32 dtlb_hi3;
++ __u32 _unused33;
++ volatile __u32 dtlb_lo3;
+
+- u32 _unused34[0x0392];
++ __u32 _unused34[0x0392];
+
+- u32 _unused35;
+- volatile u32 rpsscounter; /* Chirps at 100ns */
++ __u32 _unused35;
++ volatile __u32 rpsscounter; /* Chirps at 100ns */
+
+- u32 _unused36[0x1000/4-2*4];
++ __u32 _unused36[0x1000/4-2*4];
+
+- u32 _unused37;
+- volatile u32 maddronly; /* Address DMA goes at */
+- u32 _unused38;
+- volatile u32 maddrpdeflts; /* Same as above, plus set defaults */
+- u32 _unused39;
+- volatile u32 dmasz; /* DMA count */
+- u32 _unused40;
+- volatile u32 ssize; /* DMA stride size */
+- u32 _unused41;
+- volatile u32 gmaddronly; /* Set GIO DMA but don't start trans */
+- u32 _unused42;
+- volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
+- u32 _unused43;
+- volatile u32 dmamode; /* DMA mode config bit settings */
+- u32 _unused44;
+- volatile u32 dmaccount; /* Zoom and byte count for DMA */
+- u32 _unused45;
+- volatile u32 dmastart; /* Pedal to the metal. */
+- u32 _unused46;
+- volatile u32 dmarunning; /* DMA op is in progress */
+- u32 _unused47;
+- volatile u32 maddrdefstart; /* Set dma addr, defaults, and kick it */
++ __u32 _unused37;
++ volatile __u32 maddronly; /* Address DMA goes at */
++ __u32 _unused38;
++ volatile __u32 maddrpdeflts; /* Same as above, plus set defaults */
++ __u32 _unused39;
++ volatile __u32 dmasz; /* DMA count */
++ __u32 _unused40;
++ volatile __u32 ssize; /* DMA stride size */
++ __u32 _unused41;
++ volatile __u32 gmaddronly; /* Set GIO DMA but don't start trans */
++ __u32 _unused42;
++ volatile __u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
++ __u32 _unused43;
++ volatile __u32 dmamode; /* DMA mode config bit settings */
++ __u32 _unused44;
++ volatile __u32 dmaccount; /* Zoom and byte count for DMA */
++ __u32 _unused45;
++ volatile __u32 dmastart; /* Pedal to the metal. */
++ __u32 _unused46;
++ volatile __u32 dmarunning; /* DMA op is in progress */
++ __u32 _unused47;
++ volatile __u32 maddrdefstart; /* Set dma addr, defaults, and kick it */
+ };
+
+ extern struct sgimc_regs *sgimc;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgiarcs.h linux-libc-headers-2.6.8.0/include/asm-mips/sgiarcs.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sgiarcs.h 2004-03-28 07:51:52.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sgiarcs.h 2004-08-26 05:21:53.000000000 -0500
+@@ -164,11 +164,11 @@
+ /* This prom has a bolixed design. */
+ struct linux_bigint {
+ #ifdef __MIPSEL__
+- u32 lo;
+- s32 hi;
++ __u32 lo;
++ __s32 hi;
+ #else /* !(__MIPSEL__) */
+- s32 hi;
+- u32 lo;
++ __s32 hi;
++ __u32 lo;
+ #endif
+ };
+
+@@ -366,7 +366,7 @@
+ * Macros for calling a 32-bit ARC implementation from 64-bit code
+ */
+
+-#if defined(CONFIG_MIPS64) && defined(CONFIG_ARC32)
++#if defined(__mips64) && defined(CONFIG_ARC32)
+
+ #define __arc_clobbers \
+ "$2","$3" /* ... */, "$8","$9","$10","$11", \
+@@ -475,10 +475,10 @@
+ __res; \
+ })
+
+-#endif /* defined(CONFIG_MIPS64) && defined(CONFIG_ARC32) */
++#endif /* defined(__mips64) && defined(CONFIG_ARC32) */
+
+-#if (defined(CONFIG_MIPS32) && defined(CONFIG_ARC32)) || \
+- (defined(CONFIG_MIPS64) && defined(CONFIG_ARC64))
++#if (!defined(__mips64) && defined(CONFIG_ARC32)) || \
++ (defined(__mips64) && defined(CONFIG_ARC64))
+
+ #define ARC_CALL0(dest) \
+ ({ long __res; \
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/siginfo.h linux-libc-headers-2.6.8.0/include/asm-mips/siginfo.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/siginfo.h 2004-06-09 07:00:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/siginfo.h 2004-08-26 05:14:41.000000000 -0500
+@@ -66,10 +66,10 @@
+
+ /* SIGPOLL, SIGXFSZ (To do ...) */
+ struct {
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ long _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ #endif
+ int _fd;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sim.h linux-libc-headers-2.6.8.0/include/asm-mips/sim.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sim.h 2004-03-28 07:51:52.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sim.h 2004-08-26 05:17:16.000000000 -0500
+@@ -18,7 +18,7 @@
+ #define __str2(x) #x
+ #define __str(x) __str2(x)
+
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+
+ #define save_static_function(symbol) \
+ __asm__ ( \
+@@ -43,9 +43,9 @@
+
+ #define nabi_no_regargs
+
+-#endif /* CONFIG_MIPS32 */
++#endif /* ndef __mips64 */
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+
+ #define save_static_function(symbol) \
+ __asm__ ( \
+@@ -78,6 +78,6 @@
+ unsigned long __dummy6, \
+ unsigned long __dummy7,
+
+-#endif /* CONFIG_MIPS64 */
++#endif /* __mips64 */
+
+ #endif /* _ASM_SIM_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/arch.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/arch.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/arch.h 2004-06-09 07:00:42.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/arch.h 2004-08-26 05:26:16.000000000 -0500
+@@ -17,8 +17,8 @@
+ #include <asm/sn/sn0/arch.h>
+ #endif
+
+-typedef u64 hubreg_t;
+-typedef u64 nic_t;
++typedef __u64 hubreg_t;
++typedef __u64 nic_t;
+
+ #define cputonasid(cpu) (cpu_data[(cpu)].p_nasid)
+ #define cputoslice(cpu) (cpu_data[(cpu)].p_slice)
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/gda.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/gda.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/gda.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/gda.h 2004-08-26 05:26:30.000000000 -0500
+@@ -44,11 +44,11 @@
+ #ifndef __ASSEMBLY__
+
+ typedef struct gda {
+- u32 g_magic; /* GDA magic number */
+- u16 g_version; /* Version of this structure */
+- u16 g_masterid; /* The NASID:CPUNUM of the master cpu */
+- u32 g_promop; /* Passes requests from the kernel to prom */
+- u32 g_vds; /* Store the virtual dipswitches here */
++ __u32 g_magic; /* GDA magic number */
++ __u16 g_version; /* Version of this structure */
++ __u16 g_masterid; /* The NASID:CPUNUM of the master cpu */
++ __u32 g_promop; /* Passes requests from the kernel to prom */
++ __u32 g_vds; /* Store the virtual dipswitches here */
+ void **g_hooked_norm;/* ptr to pda loc for norm hndlr */
+ void **g_hooked_utlb;/* ptr to pda loc for utlb hndlr */
+ void **g_hooked_xtlb;/* ptr to pda loc for xtlb hndlr */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/ioc3.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/ioc3.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/ioc3.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/ioc3.h 2004-08-26 05:26:06.000000000 -0500
+@@ -8,23 +8,23 @@
+ /* SUPERIO uart register map */
+ typedef volatile struct ioc3_uartregs {
+ union {
+- volatile u8 rbr; /* read only, DLAB == 0 */
+- volatile u8 thr; /* write only, DLAB == 0 */
+- volatile u8 dll; /* DLAB == 1 */
++ volatile __u8 rbr; /* read only, DLAB == 0 */
++ volatile __u8 thr; /* write only, DLAB == 0 */
++ volatile __u8 dll; /* DLAB == 1 */
+ } u1;
+ union {
+- volatile u8 ier; /* DLAB == 0 */
+- volatile u8 dlm; /* DLAB == 1 */
++ volatile __u8 ier; /* DLAB == 0 */
++ volatile __u8 dlm; /* DLAB == 1 */
+ } u2;
+ union {
+- volatile u8 iir; /* read only */
+- volatile u8 fcr; /* write only */
++ volatile __u8 iir; /* read only */
++ volatile __u8 fcr; /* write only */
+ } u3;
+- volatile u8 iu_lcr;
+- volatile u8 iu_mcr;
+- volatile u8 iu_lsr;
+- volatile u8 iu_msr;
+- volatile u8 iu_scr;
++ volatile __u8 iu_lcr;
++ volatile __u8 iu_mcr;
++ volatile __u8 iu_lsr;
++ volatile __u8 iu_msr;
++ volatile __u8 iu_scr;
+ } ioc3_uregs_t;
+
+ #define iu_rbr u1.rbr
+@@ -36,29 +36,29 @@
+ #define iu_fcr u3.fcr
+
+ struct ioc3_sioregs {
+- volatile u8 fill[0x141]; /* starts at 0x141 */
++ volatile __u8 fill[0x141]; /* starts at 0x141 */
+
+- volatile u8 uartc;
+- volatile u8 kbdcg;
++ volatile __u8 uartc;
++ volatile __u8 kbdcg;
+
+- volatile u8 fill0[0x150 - 0x142 - 1];
++ volatile __u8 fill0[0x150 - 0x142 - 1];
+
+- volatile u8 pp_data;
+- volatile u8 pp_dsr;
+- volatile u8 pp_dcr;
++ volatile __u8 pp_data;
++ volatile __u8 pp_dsr;
++ volatile __u8 pp_dcr;
+
+- volatile u8 fill1[0x158 - 0x152 - 1];
++ volatile __u8 fill1[0x158 - 0x152 - 1];
+
+- volatile u8 pp_fifa;
+- volatile u8 pp_cfgb;
+- volatile u8 pp_ecr;
++ volatile __u8 pp_fifa;
++ volatile __u8 pp_cfgb;
++ volatile __u8 pp_ecr;
+
+- volatile u8 fill2[0x168 - 0x15a - 1];
++ volatile __u8 fill2[0x168 - 0x15a - 1];
+
+- volatile u8 rtcad;
+- volatile u8 rtcdat;
++ volatile __u8 rtcad;
++ volatile __u8 rtcdat;
+
+- volatile u8 fill3[0x170 - 0x169 - 1];
++ volatile __u8 fill3[0x170 - 0x169 - 1];
+
+ struct ioc3_uartregs uartb; /* 0x20170 */
+ struct ioc3_uartregs uarta; /* 0x20178 */
+@@ -66,103 +66,103 @@
+
+ /* Register layout of IOC3 in configuration space. */
+ struct ioc3 {
+- volatile u32 pad0[7]; /* 0x00000 */
+- volatile u32 sio_ir; /* 0x0001c */
+- volatile u32 sio_ies; /* 0x00020 */
+- volatile u32 sio_iec; /* 0x00024 */
+- volatile u32 sio_cr; /* 0x00028 */
+- volatile u32 int_out; /* 0x0002c */
+- volatile u32 mcr; /* 0x00030 */
++ volatile __u32 pad0[7]; /* 0x00000 */
++ volatile __u32 sio_ir; /* 0x0001c */
++ volatile __u32 sio_ies; /* 0x00020 */
++ volatile __u32 sio_iec; /* 0x00024 */
++ volatile __u32 sio_cr; /* 0x00028 */
++ volatile __u32 int_out; /* 0x0002c */
++ volatile __u32 mcr; /* 0x00030 */
+
+ /* General Purpose I/O registers */
+- volatile u32 gpcr_s; /* 0x00034 */
+- volatile u32 gpcr_c; /* 0x00038 */
+- volatile u32 gpdr; /* 0x0003c */
+- volatile u32 gppr_0; /* 0x00040 */
+- volatile u32 gppr_1; /* 0x00044 */
+- volatile u32 gppr_2; /* 0x00048 */
+- volatile u32 gppr_3; /* 0x0004c */
+- volatile u32 gppr_4; /* 0x00050 */
+- volatile u32 gppr_5; /* 0x00054 */
+- volatile u32 gppr_6; /* 0x00058 */
+- volatile u32 gppr_7; /* 0x0005c */
+- volatile u32 gppr_8; /* 0x00060 */
+- volatile u32 gppr_9; /* 0x00064 */
+- volatile u32 gppr_10; /* 0x00068 */
+- volatile u32 gppr_11; /* 0x0006c */
+- volatile u32 gppr_12; /* 0x00070 */
+- volatile u32 gppr_13; /* 0x00074 */
+- volatile u32 gppr_14; /* 0x00078 */
+- volatile u32 gppr_15; /* 0x0007c */
++ volatile __u32 gpcr_s; /* 0x00034 */
++ volatile __u32 gpcr_c; /* 0x00038 */
++ volatile __u32 gpdr; /* 0x0003c */
++ volatile __u32 gppr_0; /* 0x00040 */
++ volatile __u32 gppr_1; /* 0x00044 */
++ volatile __u32 gppr_2; /* 0x00048 */
++ volatile __u32 gppr_3; /* 0x0004c */
++ volatile __u32 gppr_4; /* 0x00050 */
++ volatile __u32 gppr_5; /* 0x00054 */
++ volatile __u32 gppr_6; /* 0x00058 */
++ volatile __u32 gppr_7; /* 0x0005c */
++ volatile __u32 gppr_8; /* 0x00060 */
++ volatile __u32 gppr_9; /* 0x00064 */
++ volatile __u32 gppr_10; /* 0x00068 */
++ volatile __u32 gppr_11; /* 0x0006c */
++ volatile __u32 gppr_12; /* 0x00070 */
++ volatile __u32 gppr_13; /* 0x00074 */
++ volatile __u32 gppr_14; /* 0x00078 */
++ volatile __u32 gppr_15; /* 0x0007c */
+
+ /* Parallel Port Registers */
+- volatile u32 ppbr_h_a; /* 0x00080 */
+- volatile u32 ppbr_l_a; /* 0x00084 */
+- volatile u32 ppcr_a; /* 0x00088 */
+- volatile u32 ppcr; /* 0x0008c */
+- volatile u32 ppbr_h_b; /* 0x00090 */
+- volatile u32 ppbr_l_b; /* 0x00094 */
+- volatile u32 ppcr_b; /* 0x00098 */
++ volatile __u32 ppbr_h_a; /* 0x00080 */
++ volatile __u32 ppbr_l_a; /* 0x00084 */
++ volatile __u32 ppcr_a; /* 0x00088 */
++ volatile __u32 ppcr; /* 0x0008c */
++ volatile __u32 ppbr_h_b; /* 0x00090 */
++ volatile __u32 ppbr_l_b; /* 0x00094 */
++ volatile __u32 ppcr_b; /* 0x00098 */
+
+ /* Keyboard and Mouse Registers */
+- volatile u32 km_csr; /* 0x0009c */
+- volatile u32 k_rd; /* 0x000a0 */
+- volatile u32 m_rd; /* 0x000a4 */
+- volatile u32 k_wd; /* 0x000a8 */
+- volatile u32 m_wd; /* 0x000ac */
++ volatile __u32 km_csr; /* 0x0009c */
++ volatile __u32 k_rd; /* 0x000a0 */
++ volatile __u32 m_rd; /* 0x000a4 */
++ volatile __u32 k_wd; /* 0x000a8 */
++ volatile __u32 m_wd; /* 0x000ac */
+
+ /* Serial Port Registers */
+- volatile u32 sbbr_h; /* 0x000b0 */
+- volatile u32 sbbr_l; /* 0x000b4 */
+- volatile u32 sscr_a; /* 0x000b8 */
+- volatile u32 stpir_a; /* 0x000bc */
+- volatile u32 stcir_a; /* 0x000c0 */
+- volatile u32 srpir_a; /* 0x000c4 */
+- volatile u32 srcir_a; /* 0x000c8 */
+- volatile u32 srtr_a; /* 0x000cc */
+- volatile u32 shadow_a; /* 0x000d0 */
+- volatile u32 sscr_b; /* 0x000d4 */
+- volatile u32 stpir_b; /* 0x000d8 */
+- volatile u32 stcir_b; /* 0x000dc */
+- volatile u32 srpir_b; /* 0x000e0 */
+- volatile u32 srcir_b; /* 0x000e4 */
+- volatile u32 srtr_b; /* 0x000e8 */
+- volatile u32 shadow_b; /* 0x000ec */
++ volatile __u32 sbbr_h; /* 0x000b0 */
++ volatile __u32 sbbr_l; /* 0x000b4 */
++ volatile __u32 sscr_a; /* 0x000b8 */
++ volatile __u32 stpir_a; /* 0x000bc */
++ volatile __u32 stcir_a; /* 0x000c0 */
++ volatile __u32 srpir_a; /* 0x000c4 */
++ volatile __u32 srcir_a; /* 0x000c8 */
++ volatile __u32 srtr_a; /* 0x000cc */
++ volatile __u32 shadow_a; /* 0x000d0 */
++ volatile __u32 sscr_b; /* 0x000d4 */
++ volatile __u32 stpir_b; /* 0x000d8 */
++ volatile __u32 stcir_b; /* 0x000dc */
++ volatile __u32 srpir_b; /* 0x000e0 */
++ volatile __u32 srcir_b; /* 0x000e4 */
++ volatile __u32 srtr_b; /* 0x000e8 */
++ volatile __u32 shadow_b; /* 0x000ec */
+
+ /* Ethernet Registers */
+- volatile u32 emcr; /* 0x000f0 */
+- volatile u32 eisr; /* 0x000f4 */
+- volatile u32 eier; /* 0x000f8 */
+- volatile u32 ercsr; /* 0x000fc */
+- volatile u32 erbr_h; /* 0x00100 */
+- volatile u32 erbr_l; /* 0x00104 */
+- volatile u32 erbar; /* 0x00108 */
+- volatile u32 ercir; /* 0x0010c */
+- volatile u32 erpir; /* 0x00110 */
+- volatile u32 ertr; /* 0x00114 */
+- volatile u32 etcsr; /* 0x00118 */
+- volatile u32 ersr; /* 0x0011c */
+- volatile u32 etcdc; /* 0x00120 */
+- volatile u32 ebir; /* 0x00124 */
+- volatile u32 etbr_h; /* 0x00128 */
+- volatile u32 etbr_l; /* 0x0012c */
+- volatile u32 etcir; /* 0x00130 */
+- volatile u32 etpir; /* 0x00134 */
+- volatile u32 emar_h; /* 0x00138 */
+- volatile u32 emar_l; /* 0x0013c */
+- volatile u32 ehar_h; /* 0x00140 */
+- volatile u32 ehar_l; /* 0x00144 */
+- volatile u32 micr; /* 0x00148 */
+- volatile u32 midr_r; /* 0x0014c */
+- volatile u32 midr_w; /* 0x00150 */
+- volatile u32 pad1[(0x20000 - 0x00154) / 4];
++ volatile __u32 emcr; /* 0x000f0 */
++ volatile __u32 eisr; /* 0x000f4 */
++ volatile __u32 eier; /* 0x000f8 */
++ volatile __u32 ercsr; /* 0x000fc */
++ volatile __u32 erbr_h; /* 0x00100 */
++ volatile __u32 erbr_l; /* 0x00104 */
++ volatile __u32 erbar; /* 0x00108 */
++ volatile __u32 ercir; /* 0x0010c */
++ volatile __u32 erpir; /* 0x00110 */
++ volatile __u32 ertr; /* 0x00114 */
++ volatile __u32 etcsr; /* 0x00118 */
++ volatile __u32 ersr; /* 0x0011c */
++ volatile __u32 etcdc; /* 0x00120 */
++ volatile __u32 ebir; /* 0x00124 */
++ volatile __u32 etbr_h; /* 0x00128 */
++ volatile __u32 etbr_l; /* 0x0012c */
++ volatile __u32 etcir; /* 0x00130 */
++ volatile __u32 etpir; /* 0x00134 */
++ volatile __u32 emar_h; /* 0x00138 */
++ volatile __u32 emar_l; /* 0x0013c */
++ volatile __u32 ehar_h; /* 0x00140 */
++ volatile __u32 ehar_l; /* 0x00144 */
++ volatile __u32 micr; /* 0x00148 */
++ volatile __u32 midr_r; /* 0x0014c */
++ volatile __u32 midr_w; /* 0x00150 */
++ volatile __u32 pad1[(0x20000 - 0x00154) / 4];
+
+ /* SuperIO Registers XXX */
+ struct ioc3_sioregs sregs; /* 0x20000 */
+- volatile u32 pad2[(0x40000 - 0x20180) / 4];
++ volatile __u32 pad2[(0x40000 - 0x20180) / 4];
+
+ /* SSRAM Diagnostic Access */
+- volatile u32 ssram[(0x80000 - 0x40000) / 4];
++ volatile __u32 ssram[(0x80000 - 0x40000) / 4];
+
+ /* Bytebus device offsets
+ 0x80000 - Access to the generic devices selected with DEV0
+@@ -179,8 +179,8 @@
+ * Ethernet RX Buffer
+ */
+ struct ioc3_erxbuf {
+- u32 w0; /* first word (valid,bcnt,cksum) */
+- u32 err; /* second word various errors */
++ __u32 w0; /* first word (valid,bcnt,cksum) */
++ __u32 err; /* second word various errors */
+ /* next comes n bytes of padding */
+ /* then the received ethernet frame itself */
+ };
+@@ -208,11 +208,11 @@
+ */
+ #define ETXD_DATALEN 104
+ struct ioc3_etxd {
+- u32 cmd; /* command field */
+- u32 bufcnt; /* buffer counts field */
+- u64 p1; /* buffer pointer 1 */
+- u64 p2; /* buffer pointer 2 */
+- u8 data[ETXD_DATALEN]; /* opt. tx data */
++ __u32 cmd; /* command field */
++ __u32 bufcnt; /* buffer counts field */
++ __u64 p1; /* buffer pointer 1 */
++ __u64 p2; /* buffer pointer 2 */
++ __u8 data[ETXD_DATALEN]; /* opt. tx data */
+ };
+
+ #define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/klconfig.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/klconfig.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/klconfig.h 2004-03-28 07:51:55.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/klconfig.h 2004-08-26 05:26:13.000000000 -0500
+@@ -64,9 +64,9 @@
+ #define KLCFGINFO_MAGIC 0xbeedbabe
+
+ #ifdef FRUTEST
+-typedef u64 klconf_off_t;
++typedef __u64 klconf_off_t;
+ #else
+-typedef s32 klconf_off_t;
++typedef __s32 klconf_off_t;
+ #endif
+
+ /*
+@@ -160,8 +160,8 @@
+ /* Functions/macros needed to use this structure */
+
+ typedef struct kl_config_hdr {
+- u64 ch_magic; /* set this to KLCFGINFO_MAGIC */
+- u32 ch_version; /* structure version number */
++ __u64 ch_magic; /* set this to KLCFGINFO_MAGIC */
++ __u32 ch_version; /* structure version number */
+ klconf_off_t ch_malloc_hdr_off; /* offset of ch_malloc_hdr */
+ klconf_off_t ch_cons_off; /* offset of ch_cons */
+ klconf_off_t ch_board_info; /* the link list of boards */
+@@ -609,14 +609,14 @@
+
+ /* Info holders for various hardware components */
+
+-typedef u64 *pci_t;
+-typedef u64 *vmeb_t;
+-typedef u64 *vmed_t;
+-typedef u64 *fddi_t;
+-typedef u64 *scsi_t;
+-typedef u64 *mio_t;
+-typedef u64 *graphics_t;
+-typedef u64 *router_t;
++typedef __u64 *pci_t;
++typedef __u64 *vmeb_t;
++typedef __u64 *vmed_t;
++typedef __u64 *fddi_t;
++typedef __u64 *scsi_t;
++typedef __u64 *mio_t;
++typedef __u64 *graphics_t;
++typedef __u64 *router_t;
+
+ /*
+ * The port info in ip27_cfg area translates to a lboart_t in the
+@@ -659,7 +659,7 @@
+ klport_t hub_port; /* hub is connected to this */
+ nic_t hub_box_nic; /* nic of containing box */
+ klconf_off_t hub_mfg_nic; /* MFG NIC string */
+- u64 hub_speed; /* Speed of hub in HZ */
++ __u64 hub_speed; /* Speed of hub in HZ */
+ } klhub_t ;
+
+ typedef struct klhub_uart_s { /* HUB */
+@@ -716,8 +716,8 @@
+ #define MAX_PCI_SLOTS 8
+
+ typedef struct klpci_device_s {
+- s32 pci_device_id; /* 32 bits of vendor/device ID. */
+- s32 pci_device_pad; /* 32 bits of padding. */
++ __s32 pci_device_id; /* 32 bits of vendor/device ID. */
++ __s32 pci_device_pad; /* 32 bits of padding. */
+ } klpci_device_t;
+
+ #define BRIDGE_STRUCT_VERSION 2
+@@ -767,7 +767,7 @@
+ nic_t rou_box_nic ; /* nic of the containing module */
+ klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */
+ klconf_off_t rou_mfg_nic ; /* MFG NIC string */
+- u64 rou_vector; /* vector from master node */
++ __u64 rou_vector; /* vector from master node */
+ } klrou_t ;
+
+ /*
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/kldir.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/kldir.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/kldir.h 2004-01-17 17:03:49.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/kldir.h 2004-08-26 05:26:25.000000000 -0500
+@@ -210,7 +210,7 @@
+
+ #ifndef __ASSEMBLY__
+ typedef struct kldir_ent_s {
+- u64 magic; /* Indicates validity of entry */
++ __u64 magic; /* Indicates validity of entry */
+ off_t offset; /* Offset from start of node space */
+ #if defined(CONFIG_SGI_IO) /* FIXME */
+ __psunsigned_t pointer; /* Pointer to area in some cases */
+@@ -218,7 +218,7 @@
+ unsigned long pointer; /* Pointer to area in some cases */
+ #endif
+ size_t size; /* Size in bytes */
+- u64 count; /* Repeat count if array, 1 if not */
++ __u64 count; /* Repeat count if array, 1 if not */
+ size_t stride; /* Stride if array, 0 if not */
+ char rsvd[16]; /* Pad entry to 0x40 bytes */
+ /* NOTE: These 16 bytes are used in the Partition KLDIR
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/launch.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/launch.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/launch.h 2004-01-17 17:03:49.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/launch.h 2004-08-26 05:25:52.000000000 -0500
+@@ -62,14 +62,14 @@
+ #ifndef __ASSEMBLY__
+
+ typedef int launch_state_t;
+-typedef void (*launch_proc_t)(u64 call_parm);
++typedef void (*launch_proc_t)(__u64 call_parm);
+
+ typedef struct launch_s {
+- volatile u64 magic; /* Magic number */
+- volatile u64 busy; /* Slave currently active */
++ volatile __u64 magic; /* Magic number */
++ volatile __u64 busy; /* Slave currently active */
+ volatile launch_proc_t call_addr; /* Func. for slave to call */
+- volatile u64 call_addr_c; /* 1's complement of call_addr*/
+- volatile u64 call_parm; /* Single parm passed to call*/
++ volatile __u64 call_addr_c; /* 1's complement of call_addr*/
++ volatile __u64 call_parm; /* Single parm passed to call*/
+ volatile void *stack_addr; /* Stack pointer for slave function */
+ volatile void *gp_addr; /* Global pointer for slave func. */
+ volatile char *bevutlb;/* Address of bev utlb ex handler */
+@@ -84,7 +84,7 @@
+
+ #define LAUNCH_SLAVE (*(void (*)(int nasid, int cpu, \
+ launch_proc_t call_addr, \
+- u64 call_parm, \
++ __u64 call_parm, \
+ void *stack_addr, \
+ void *gp_addr)) \
+ IP27PROM_LAUNCHSLAVE)
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubio.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubio.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubio.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubio.h 2004-08-26 05:27:21.000000000 -0500
+@@ -172,9 +172,9 @@
+ #ifndef __ASSEMBLY__
+
+ typedef union hubii_wid_u {
+- u64 wid_reg_value;
++ __u64 wid_reg_value;
+ struct {
+- u64 wid_rsvd: 32, /* unused */
++ __u64 wid_rsvd: 32, /* unused */
+ wid_rev_num: 4, /* revision number */
+ wid_part_num: 16, /* the widget type: hub=c101 */
+ wid_mfg_num: 11, /* Manufacturer id (IBM) */
+@@ -184,9 +184,9 @@
+
+
+ typedef union hubii_wcr_u {
+- u64 wcr_reg_value;
++ __u64 wcr_reg_value;
+ struct {
+- u64 wcr_rsvd: 41, /* unused */
++ __u64 wcr_rsvd: 41, /* unused */
+ wcr_e_thresh: 5, /* elasticity threshold */
+ wcr_dir_con: 1, /* widget direct connect */
+ wcr_f_bad_pkt: 1, /* Force bad llp pkt enable */
+@@ -200,9 +200,9 @@
+ #define iwcr_dir_con wcr_fields_s.wcr_dir_con
+
+ typedef union hubii_wstat_u {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd1: 31,
++ __u64 rsvd1: 31,
+ crazy: 1, /* Crazy bit */
+ rsvd2: 8,
+ llp_tx_cnt: 8, /* LLP Xmit retry counter */
+@@ -217,9 +217,9 @@
+
+
+ typedef union hubii_ilcsr_u {
+- u64 icsr_reg_value;
++ __u64 icsr_reg_value;
+ struct {
+- u64 icsr_rsvd: 22, /* unused */
++ __u64 icsr_rsvd: 22, /* unused */
+ icsr_max_burst: 10, /* max burst */
+ icsr_rsvd4: 6, /* reserved */
+ icsr_max_retry: 10, /* max retry */
+@@ -237,9 +237,9 @@
+
+
+ typedef union hubii_iowa_u {
+- u64 iowa_reg_value;
++ __u64 iowa_reg_value;
+ struct {
+- u64 iowa_rsvd: 48, /* unused */
++ __u64 iowa_rsvd: 48, /* unused */
+ iowa_wxoac: 8, /* xtalk widget access bits */
+ iowa_rsvd1: 7, /* xtalk widget access bits */
+ iowa_w0oac: 1; /* xtalk widget access bits */
+@@ -247,9 +247,9 @@
+ } hubii_iowa_t;
+
+ typedef union hubii_iiwa_u {
+- u64 iiwa_reg_value;
++ __u64 iiwa_reg_value;
+ struct {
+- u64 iiwa_rsvd: 48, /* unused */
++ __u64 iiwa_rsvd: 48, /* unused */
+ iiwa_wxiac: 8, /* hub wid access bits */
+ iiwa_rsvd1: 7, /* reserved */
+ iiwa_w0iac: 1; /* hub wid0 access */
+@@ -257,9 +257,9 @@
+ } hubii_iiwa_t;
+
+ typedef union hubii_illr_u {
+- u64 illr_reg_value;
++ __u64 illr_reg_value;
+ struct {
+- u64 illr_rsvd: 32, /* unused */
++ __u64 illr_rsvd: 32, /* unused */
+ illr_cb_cnt: 16, /* checkbit error count */
+ illr_sn_cnt: 16; /* sequence number count */
+ } illr_fields_s;
+@@ -271,9 +271,9 @@
+ /* io_perf_sel allows the caller to specify what tests will be
+ performed */
+ typedef union io_perf_sel {
+- u64 perf_sel_reg;
++ __u64 perf_sel_reg;
+ struct {
+- u64 perf_rsvd : 48,
++ __u64 perf_rsvd : 48,
+ perf_icct : 8,
+ perf_ippr1 : 4,
+ perf_ippr0 : 4;
+@@ -284,9 +284,9 @@
+ hardware problems there is only one counter, not two. */
+
+ typedef union io_perf_cnt {
+- u64 perf_cnt;
++ __u64 perf_cnt;
+ struct {
+- u64 perf_rsvd1 : 32,
++ __u64 perf_rsvd1 : 32,
+ perf_rsvd2 : 12,
+ perf_cnt : 20;
+ } perf_cnt_bits;
+@@ -442,9 +442,9 @@
+ */
+ #ifndef __ASSEMBLY__
+ typedef union icrba_u {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 resvd: 6,
++ __u64 resvd: 6,
+ stall_bte0: 1, /* Stall BTE 0 */
+ stall_bte1: 1, /* Stall BTE 1 */
+ error: 1, /* CRB has an error */
+@@ -464,10 +464,10 @@
+ runtime selection of the format based on the REV_ID field of the
+ NI_STATUS_REV_ID register. */
+ typedef union h1_icrba_u {
+- u64 reg_value;
++ __u64 reg_value;
+
+ struct {
+- u64 resvd: 6,
++ __u64 resvd: 6,
+ unused: 1, /* Unused but RW!! */
+ error: 1, /* CRB has an error */
+ ecode: 4, /* Error Code */
+@@ -525,9 +525,9 @@
+ */
+ #ifndef __ASSEMBLY__
+ typedef union icrbb_u {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd1: 5,
++ __u64 rsvd1: 5,
+ btenum: 1, /* BTE to which entry belongs to */
+ cohtrans: 1, /* Coherent transaction */
+ xtsize: 2, /* Xtalk operation size
+@@ -567,9 +567,9 @@
+ runtime selection of the format based on the REV_ID field of the
+ NI_STATUS_REV_ID register. */
+ typedef union h1_icrbb_u {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd1: 5,
++ __u64 rsvd1: 5,
+ btenum: 1, /* BTE to which entry belongs to */
+ cohtrans: 1, /* Coherent transaction */
+ xtsize: 2, /* Xtalk operation size
+@@ -683,9 +683,9 @@
+ #ifndef __ASSEMBLY__
+
+ typedef union icrbc_s {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd: 6,
++ __u64 rsvd: 6,
+ sleep: 1,
+ pricnt: 4, /* Priority count sent with Read req */
+ pripsc: 4, /* Priority Pre scalar */
+@@ -720,9 +720,9 @@
+
+ #ifndef __ASSEMBLY__
+ typedef union icrbd_s {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd: 38,
++ __u64 rsvd: 38,
+ toutvld: 1, /* Timeout in progress for this CRB */
+ ctxtvld: 1, /* Context field below is valid */
+ rsvd2: 1,
+@@ -742,9 +742,9 @@
+
+
+ typedef union hubii_ifdr_u {
+- u64 hi_ifdr_value;
++ __u64 hi_ifdr_value;
+ struct {
+- u64 ifdr_rsvd: 49,
++ __u64 ifdr_rsvd: 49,
+ ifdr_maxrp: 7,
+ ifdr_rsvd1: 1,
+ ifdr_maxrq: 7;
+@@ -801,9 +801,9 @@
+ #ifndef __ASSEMBLY__
+
+ typedef union iprte_a {
+- u64 entry;
++ __u64 entry;
+ struct {
+- u64 rsvd1 : 7, /* Reserved field */
++ __u64 rsvd1 : 7, /* Reserved field */
+ valid : 1, /* Maps to a timeout entry */
+ rsvd2 : 1,
+ srcnode : 9, /* Node which did this PIO */
+@@ -835,9 +835,9 @@
+ */
+
+ typedef union iprb_u {
+- u64 reg_value;
++ __u64 reg_value;
+ struct {
+- u64 rsvd1: 15,
++ __u64 rsvd1: 15,
+ error: 1, /* Widget rcvd wr resp pkt w/ error */
+ ovflow: 5, /* Over flow count. perf measurement */
+ fire_and_forget: 1, /* Launch Write without response */
+@@ -877,9 +877,9 @@
+ */
+ #ifndef __ASSEMBLY__
+ typedef union icrbp_a {
+- u64 ip_reg; /* the entire register value */
++ __u64 ip_reg; /* the entire register value */
+ struct {
+- u64 error: 1, /* 63, error occurred */
++ __u64 error: 1, /* 63, error occurred */
+ ln_uce: 1, /* 62: uncorrectable memory */
+ ln_ae: 1, /* 61: protection violation */
+ ln_werr:1, /* 60: write access error */
+@@ -919,9 +919,9 @@
+
+ #ifndef __ASSEMBLY__
+ typedef union hubii_idsr {
+- u64 iin_reg;
++ __u64 iin_reg;
+ struct {
+- u64 rsvd1 : 35,
++ __u64 rsvd1 : 35,
+ isent : 1,
+ rsvd2 : 3,
+ ienable: 1,
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubmd.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubmd.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubmd.h 2004-01-17 17:03:49.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubmd.h 2004-08-26 05:27:00.000000000 -0500
+@@ -541,7 +541,7 @@
+ */
+
+ struct dir_error_reg {
+- u64 uce_vld: 1, /* 63: valid directory uce */
++ __u64 uce_vld: 1, /* 63: valid directory uce */
+ ae_vld: 1, /* 62: valid dir prot ecc error */
+ ce_vld: 1, /* 61: valid correctable ECC err*/
+ rsvd1: 19, /* 60-42: reserved */
+@@ -555,13 +555,13 @@
+ };
+
+ typedef union md_dir_error {
+- u64 derr_reg; /* the entire register */
++ __u64 derr_reg; /* the entire register */
+ struct dir_error_reg derr_fmt; /* the register format */
+ } md_dir_error_t;
+
+
+ struct mem_error_reg {
+- u64 uce_vld: 1, /* 63: valid memory uce */
++ __u64 uce_vld: 1, /* 63: valid memory uce */
+ ce_vld: 1, /* 62: valid correctable ECC err*/
+ rsvd1: 22, /* 61-40: reserved */
+ bad_syn: 8, /* 39-32: bad mem ecc syndrome */
+@@ -573,13 +573,13 @@
+
+
+ typedef union md_mem_error {
+- u64 merr_reg; /* the entire register */
++ __u64 merr_reg; /* the entire register */
+ struct mem_error_reg merr_fmt; /* format of the mem_error reg */
+ } md_mem_error_t;
+
+
+ struct proto_error_reg {
+- u64 valid: 1, /* 63: valid protocol error */
++ __u64 valid: 1, /* 63: valid protocol error */
+ rsvd1: 2, /* 62-61: reserved */
+ initiator:11, /* 60-50: id of request initiator*/
+ backoff: 2, /* 49-48: backoff control */
+@@ -594,7 +594,7 @@
+ };
+
+ typedef union md_proto_error {
+- u64 perr_reg; /* the entire register */
++ __u64 perr_reg; /* the entire register */
+ struct proto_error_reg perr_fmt; /* format of the register */
+ } md_proto_error_t;
+
+@@ -642,7 +642,7 @@
+
+
+ struct md_pdir_high_fmt {
+- u64 pd_hi_unused : 16,
++ __u64 pd_hi_unused : 16,
+ pd_hi_bvec : 38,
+ pd_hi_unused1 : 3,
+ pd_hi_ecc : 7;
+@@ -651,14 +651,14 @@
+
+ typedef union md_pdir_high {
+ /* The 48 bits of standard directory, upper word */
+- u64 pd_hi_val;
++ __u64 pd_hi_val;
+ struct md_pdir_high_fmt pd_hi_fmt;
+ }md_pdir_high_t;
+
+
+ struct md_pdir_low_shared_fmt {
+ /* The meaning of lower directory, shared */
+- u64 pds_lo_unused : 16,
++ __u64 pds_lo_unused : 16,
+ pds_lo_bvec : 26,
+ pds_lo_cnt : 6,
+ pds_lo_state : 3,
+@@ -670,7 +670,7 @@
+
+ struct md_pdir_low_exclusive_fmt {
+ /* The meaning of lower directory, exclusive */
+- u64 pde_lo_unused : 31,
++ __u64 pde_lo_unused : 31,
+ pde_lo_ptr : 11,
+ pde_lo_unused1 : 6,
+ pde_lo_state : 3,
+@@ -683,7 +683,7 @@
+
+ typedef union md_pdir_loent {
+ /* The 48 bits of premium directory, lower word */
+- u64 pd_lo_val;
++ __u64 pd_lo_val;
+ struct md_pdir_low_exclusive_fmt pde_lo_fmt;
+ struct md_pdir_low_shared_fmt pds_lo_fmt;
+ }md_pdir_low_t;
+@@ -711,25 +711,25 @@
+ } bddir_entry_t;
+
+ typedef struct dir_mem_entry {
+- u64 prcpf[MAX_REGIONS];
++ __u64 prcpf[MAX_REGIONS];
+ bddir_entry_t directory_words[MD_PAGE_SIZE/CACHE_SLINE_SIZE];
+ } dir_mem_entry_t;
+
+
+
+ typedef union md_perf_sel {
+- u64 perf_sel_reg;
++ __u64 perf_sel_reg;
+ struct {
+- u64 perf_rsvd : 60,
++ __u64 perf_rsvd : 60,
+ perf_en : 1,
+ perf_sel : 3;
+ } perf_sel_bits;
+ } md_perf_sel_t;
+
+ typedef union md_perf_cnt {
+- u64 perf_cnt;
++ __u64 perf_cnt;
+ struct {
+- u64 perf_rsvd : 44,
++ __u64 perf_rsvd : 44,
+ perf_cnt : 20;
+ } perf_cnt_bits;
+ } md_perf_cnt_t;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubni.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubni.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubni.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubni.h 2004-08-26 05:26:48.000000000 -0500
+@@ -229,9 +229,9 @@
+ #ifndef __ASSEMBLY__
+
+ typedef union hubni_port_error_u {
+- u64 nipe_reg_value;
++ __u64 nipe_reg_value;
+ struct {
+- u64 nipe_rsvd: 26, /* unused */
++ __u64 nipe_rsvd: 26, /* unused */
+ nipe_lnk_reset: 1, /* link reset */
+ nipe_intl_err: 1, /* internal error */
+ nipe_bad_msg: 1, /* bad message */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubpi.h linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubpi.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/sn/sn0/hubpi.h 2003-12-15 12:47:02.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/sn/sn0/hubpi.h 2004-08-26 05:26:36.000000000 -0500
+@@ -312,7 +312,7 @@
+ */
+
+ struct err_stack_format {
+- u64 sk_addr : 33, /* address */
++ __u64 sk_addr : 33, /* address */
+ sk_cmd : 8, /* message command */
+ sk_crb_sts : 10, /* status from RRB or WRB */
+ sk_rw_rb : 1, /* RRB == 0, WRB == 1 */
+@@ -323,12 +323,12 @@
+ };
+
+ typedef union pi_err_stack {
+- u64 pi_stk_word;
++ __u64 pi_stk_word;
+ struct err_stack_format pi_stk_fmt;
+ } pi_err_stack_t;
+
+ struct err_status0_format {
+- u64 s0_valid : 1, /* Valid */
++ __u64 s0_valid : 1, /* Valid */
+ s0_ovr_run : 1, /* Overrun, spooled to memory */
+ s0_addr : 37, /* address */
+ s0_cmd : 8, /* message command */
+@@ -338,12 +338,12 @@
+ };
+
+ typedef union pi_err_stat0 {
+- u64 pi_stat0_word;
++ __u64 pi_stat0_word;
+ struct err_status0_format pi_stat0_fmt;
+ } pi_err_stat0_t;
+
+ struct err_status1_format {
+- u64 s1_src : 11, /* message source */
++ __u64 s1_src : 11, /* message source */
+ s1_crb_sts : 10, /* status from RRB or WRB */
+ s1_rw_rb : 1, /* RRB == 0, WRB == 1 */
+ s1_crb_num : 3, /* WRB (0 to 7) or RRB (0 to 4) */
+@@ -353,11 +353,11 @@
+ };
+
+ typedef union pi_err_stat1 {
+- u64 pi_stat1_word;
++ __u64 pi_stat1_word;
+ struct err_status1_format pi_stat1_fmt;
+ } pi_err_stat1_t;
+
+-typedef u64 rtc_time_t;
++typedef __u64 rtc_time_t;
+
+ #endif /* !__ASSEMBLY__ */
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/stackframe.h linux-libc-headers-2.6.8.0/include/asm-mips/stackframe.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/stackframe.h 2004-08-18 13:15:41.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/stackframe.h 2004-08-26 05:14:41.000000000 -0500
+@@ -25,7 +25,7 @@
+
+ .macro SAVE_TEMP
+ mfhi v1
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ LONG_S $8, PT_R8(sp)
+ LONG_S $9, PT_R9(sp)
+ #endif
+@@ -55,7 +55,7 @@
+
+ #ifdef CONFIG_SMP
+ .macro get_saved_sp /* SMP variation */
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ mfc0 k0, CP0_CONTEXT
+ lui k1, %hi(kernelsp)
+ srl k0, k0, 23
+@@ -63,7 +63,7 @@
+ addu k1, k0
+ LONG_L k1, %lo(kernelsp)(k1)
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ MFC0 k1, CP0_CONTEXT
+ dsra k1, 23
+ lui k0, %hi(pgd_current)
+@@ -76,13 +76,13 @@
+ .endm
+
+ .macro set_saved_sp stackp temp temp2
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ mfc0 \temp, CP0_CONTEXT
+ srl \temp, 23
+ sll \temp, 2
+ LONG_S \stackp, kernelsp(\temp)
+ #endif
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ lw \temp, TI_CPU(gp)
+ dsll \temp, 3
+ lui \temp2, %hi(kernelsp)
+@@ -127,7 +127,7 @@
+ LONG_S $6, PT_R6(sp)
+ MFC0 v1, CP0_EPC
+ LONG_S $7, PT_R7(sp)
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ LONG_S $8, PT_R8(sp)
+ LONG_S $9, PT_R9(sp)
+ #endif
+@@ -156,7 +156,7 @@
+
+ .macro RESTORE_TEMP
+ LONG_L $24, PT_LO(sp)
+-#ifdef CONFIG_MIPS32
++#ifndef __mips64
+ LONG_L $8, PT_R8(sp)
+ LONG_L $9, PT_R9(sp)
+ #endif
+@@ -204,7 +204,7 @@
+ LONG_L $31, PT_R31(sp)
+ LONG_L $28, PT_R28(sp)
+ LONG_L $25, PT_R25(sp)
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ LONG_L $8, PT_R8(sp)
+ LONG_L $9, PT_R9(sp)
+ #endif
+@@ -249,7 +249,7 @@
+ LONG_L $31, PT_R31(sp)
+ LONG_L $28, PT_R28(sp)
+ LONG_L $25, PT_R25(sp)
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ LONG_L $8, PT_R8(sp)
+ LONG_L $9, PT_R9(sp)
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/system.h linux-libc-headers-2.6.8.0/include/asm-mips/system.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/system.h 2004-08-18 13:15:42.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/system.h 2004-08-28 18:13:39.000000000 -0500
+@@ -15,10 +15,11 @@
+ #include <asm/sgidefs.h>
+
+ #include <linux/kernel.h>
++#include <linux/linkage.h>
+
+ #include <asm/addrspace.h>
+ #include <asm/ptrace.h>
+-#include <asm/hazards.h>
++#include <asm/types.h>
+
+ __asm__ (
+ ".macro\tlocal_irq_enable\n\t"
+@@ -311,7 +312,7 @@
+ return retval;
+ }
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
+ {
+ __u64 retval;
+@@ -406,7 +407,7 @@
+ return retval;
+ }
+
+-#ifdef CONFIG_MIPS64
++#ifdef __mips64
+ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
+ unsigned long new)
+ {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/tx4927/tx4927_mips.h linux-libc-headers-2.6.8.0/include/asm-mips/tx4927/tx4927_mips.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/tx4927/tx4927_mips.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/tx4927/tx4927_mips.h 2004-08-26 05:22:30.000000000 -0500
+@@ -36,15 +36,15 @@
+ ".set\tmips0");
+ }
+
+-#define reg_rd08(r) ((u8 )(*((vu8 *)(r))))
+-#define reg_rd16(r) ((u16)(*((vu16*)(r))))
+-#define reg_rd32(r) ((u32)(*((vu32*)(r))))
+-#define reg_rd64(r) ((u64)(*((vu64*)(r))))
++#define reg_rd08(r) ((__u8 )(*((vu8 *)(r))))
++#define reg_rd16(r) ((__u16)(*((vu16*)(r))))
++#define reg_rd32(r) ((__u32)(*((vu32*)(r))))
++#define reg_rd64(r) ((__u64)(*((vu64*)(r))))
+
+-#define reg_wr08(r,v) ((*((vu8 *)(r)))=((u8 )(v)))
+-#define reg_wr16(r,v) ((*((vu16*)(r)))=((u16)(v)))
+-#define reg_wr32(r,v) ((*((vu32*)(r)))=((u32)(v)))
+-#define reg_wr64(r,v) ((*((vu64*)(r)))=((u64)(v)))
++#define reg_wr08(r,v) ((*((vu8 *)(r)))=((__u8 )(v)))
++#define reg_wr16(r,v) ((*((vu16*)(r)))=((__u16)(v)))
++#define reg_wr32(r,v) ((*((vu32*)(r)))=((__u32)(v)))
++#define reg_wr64(r,v) ((*((vu64*)(r)))=((__u64)(v)))
+
+ typedef volatile __signed char vs8;
+ typedef volatile unsigned char vu8;
+@@ -55,10 +55,10 @@
+ typedef volatile __signed int vs32;
+ typedef volatile unsigned int vu32;
+
+-typedef s8 s08;
++typedef __s8 s08;
+ typedef vs8 vs08;
+
+-typedef u8 u08;
++typedef __u8 u08;
+ typedef vu8 vu08;
+
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/unaligned.h linux-libc-headers-2.6.8.0/include/asm-mips/unaligned.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/unaligned.h 2004-08-15 15:38:27.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/asm-mips/unaligned.h 2004-08-26 05:22:21.000000000 -0500
+@@ -17,7 +17,7 @@
+ *
+ * This macro should be used for accessing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+- * e.g. retrieving a u16 value from a location not u16-aligned.
++ * e.g. retrieving a __u16 value from a location not __u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
+@@ -31,7 +31,7 @@
+ *
+ * This macro should be used for placing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+- * e.g. writing a u16 value to a location not u16-aligned.
++ * e.g. writing a __u16 value to a location not __u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/asm-mips/xtalk/xwidget.h linux-libc-headers-2.6.8.0/include/asm-mips/xtalk/xwidget.h
+--- linux-libc-headers-2.6.8.0-dist/include/asm-mips/xtalk/xwidget.h 2003-12-15 12:47:03.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/asm-mips/xtalk/xwidget.h 2004-08-26 05:23:33.000000000 -0500
+@@ -92,7 +92,7 @@
+ * defined here
+ */
+ #ifndef __ASSEMBLY__
+-typedef u32 widgetreg_t;
++typedef __u32 widgetreg_t;
+
+ /* widget configuration registers */
+ typedef volatile struct widget_cfg {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/acpi.h linux-libc-headers-2.6.8.0/include/linux/acpi.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/acpi.h 2004-08-18 13:16:01.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/acpi.h 2004-08-26 05:41:49.000000000 -0500
+@@ -51,49 +51,49 @@
+
+ struct acpi_table_rsdp {
+ char signature[8];
+- u8 checksum;
++ __u8 checksum;
+ char oem_id[6];
+- u8 revision;
+- u32 rsdt_address;
++ __u8 revision;
++ __u32 rsdt_address;
+ } __attribute__ ((packed));
+
+ struct acpi20_table_rsdp {
+ char signature[8];
+- u8 checksum;
++ __u8 checksum;
+ char oem_id[6];
+- u8 revision;
+- u32 rsdt_address;
+- u32 length;
+- u64 xsdt_address;
+- u8 ext_checksum;
+- u8 reserved[3];
++ __u8 revision;
++ __u32 rsdt_address;
++ __u32 length;
++ __u64 xsdt_address;
++ __u8 ext_checksum;
++ __u8 reserved[3];
+ } __attribute__ ((packed));
+
+ typedef struct {
+- u8 type;
+- u8 length;
++ __u8 type;
++ __u8 length;
+ } __attribute__ ((packed)) acpi_table_entry_header;
+
+ /* Root System Description Table (RSDT) */
+
+ struct acpi_table_rsdt {
+ struct acpi_table_header header;
+- u32 entry[8];
++ __u32 entry[8];
+ } __attribute__ ((packed));
+
+ /* Extended System Description Table (XSDT) */
+
+ struct acpi_table_xsdt {
+ struct acpi_table_header header;
+- u64 entry[1];
++ __u64 entry[1];
+ } __attribute__ ((packed));
+
+ /* Fixed ACPI Description Table (FADT) */
+
+ struct acpi_table_fadt {
+ struct acpi_table_header header;
+- u32 facs_addr;
+- u32 dsdt_addr;
++ __u32 facs_addr;
++ __u32 dsdt_addr;
+ /* ... */
+ } __attribute__ ((packed));
+
+@@ -101,10 +101,10 @@
+
+ struct acpi_table_madt {
+ struct acpi_table_header header;
+- u32 lapic_address;
++ __u32 lapic_address;
+ struct {
+- u32 pcat_compat:1;
+- u32 reserved:31;
++ __u32 pcat_compat:1;
++ __u32 reserved:31;
+ } flags;
+ } __attribute__ ((packed));
+
+@@ -122,85 +122,85 @@
+ };
+
+ typedef struct {
+- u16 polarity:2;
+- u16 trigger:2;
+- u16 reserved:12;
++ __u16 polarity:2;
++ __u16 trigger:2;
++ __u16 reserved:12;
+ } __attribute__ ((packed)) acpi_interrupt_flags;
+
+ struct acpi_table_lapic {
+ acpi_table_entry_header header;
+- u8 acpi_id;
+- u8 id;
++ __u8 acpi_id;
++ __u8 id;
+ struct {
+- u32 enabled:1;
+- u32 reserved:31;
++ __u32 enabled:1;
++ __u32 reserved:31;
+ } flags;
+ } __attribute__ ((packed));
+
+ struct acpi_table_ioapic {
+ acpi_table_entry_header header;
+- u8 id;
+- u8 reserved;
+- u32 address;
+- u32 global_irq_base;
++ __u8 id;
++ __u8 reserved;
++ __u32 address;
++ __u32 global_irq_base;
+ } __attribute__ ((packed));
+
+ struct acpi_table_int_src_ovr {
+ acpi_table_entry_header header;
+- u8 bus;
+- u8 bus_irq;
+- u32 global_irq;
++ __u8 bus;
++ __u8 bus_irq;
++ __u32 global_irq;
+ acpi_interrupt_flags flags;
+ } __attribute__ ((packed));
+
+ struct acpi_table_nmi_src {
+ acpi_table_entry_header header;
+ acpi_interrupt_flags flags;
+- u32 global_irq;
++ __u32 global_irq;
+ } __attribute__ ((packed));
+
+ struct acpi_table_lapic_nmi {
+ acpi_table_entry_header header;
+- u8 acpi_id;
++ __u8 acpi_id;
+ acpi_interrupt_flags flags;
+- u8 lint;
++ __u8 lint;
+ } __attribute__ ((packed));
+
+ struct acpi_table_lapic_addr_ovr {
+ acpi_table_entry_header header;
+- u8 reserved[2];
+- u64 address;
++ __u8 reserved[2];
++ __u64 address;
+ } __attribute__ ((packed));
+
+ struct acpi_table_iosapic {
+ acpi_table_entry_header header;
+- u8 id;
+- u8 reserved;
+- u32 global_irq_base;
+- u64 address;
++ __u8 id;
++ __u8 reserved;
++ __u32 global_irq_base;
++ __u64 address;
+ } __attribute__ ((packed));
+
+ struct acpi_table_lsapic {
+ acpi_table_entry_header header;
+- u8 acpi_id;
+- u8 id;
+- u8 eid;
+- u8 reserved[3];
++ __u8 acpi_id;
++ __u8 id;
++ __u8 eid;
++ __u8 reserved[3];
+ struct {
+- u32 enabled:1;
+- u32 reserved:31;
++ __u32 enabled:1;
++ __u32 reserved:31;
+ } flags;
+ } __attribute__ ((packed));
+
+ struct acpi_table_plat_int_src {
+ acpi_table_entry_header header;
+ acpi_interrupt_flags flags;
+- u8 type; /* See acpi_interrupt_type */
+- u8 id;
+- u8 eid;
+- u8 iosapic_vector;
+- u32 global_irq;
+- u32 reserved;
++ __u8 type; /* See acpi_interrupt_type */
++ __u8 id;
++ __u8 eid;
++ __u8 iosapic_vector;
++ __u32 global_irq;
++ __u32 reserved;
+ } __attribute__ ((packed));
+
+ enum acpi_interrupt_id {
+@@ -213,21 +213,21 @@
+ #define ACPI_SPACE_MEM 0
+
+ struct acpi_gen_regaddr {
+- u8 space_id;
+- u8 bit_width;
+- u8 bit_offset;
+- u8 resv;
+- u32 addrl;
+- u32 addrh;
++ __u8 space_id;
++ __u8 bit_width;
++ __u8 bit_offset;
++ __u8 resv;
++ __u32 addrl;
++ __u32 addrh;
+ } __attribute__ ((packed));
+
+ struct acpi_table_hpet {
+ struct acpi_table_header header;
+- u32 id;
++ __u32 id;
+ struct acpi_gen_regaddr addr;
+- u8 number;
+- u16 min_tick;
+- u8 page_protect;
++ __u8 number;
++ __u16 min_tick;
++ __u8 page_protect;
+ } __attribute__ ((packed));
+
+ /*
+@@ -236,17 +236,17 @@
+ */
+ struct acpi_table_sbf
+ {
+- u8 sbf_signature[4];
+- u32 sbf_len;
+- u8 sbf_revision;
+- u8 sbf_csum;
+- u8 sbf_oemid[6];
+- u8 sbf_oemtable[8];
+- u8 sbf_revdata[4];
+- u8 sbf_creator[4];
+- u8 sbf_crearev[4];
+- u8 sbf_cmos;
+- u8 sbf_spare[3];
++ __u8 sbf_signature[4];
++ __u32 sbf_len;
++ __u8 sbf_revision;
++ __u8 sbf_csum;
++ __u8 sbf_oemid[6];
++ __u8 sbf_oemtable[8];
++ __u8 sbf_revdata[4];
++ __u8 sbf_creator[4];
++ __u8 sbf_crearev[4];
++ __u8 sbf_cmos;
++ __u8 sbf_spare[3];
+ } __attribute__ ((packed));
+
+ /*
+@@ -256,8 +256,8 @@
+
+ struct acpi_table_srat {
+ struct acpi_table_header header;
+- u32 table_revision;
+- u64 reserved;
++ __u32 table_revision;
++ __u64 reserved;
+ } __attribute__ ((packed));
+
+ enum acpi_srat_entry_id {
+@@ -268,31 +268,31 @@
+
+ struct acpi_table_processor_affinity {
+ acpi_table_entry_header header;
+- u8 proximity_domain;
+- u8 apic_id;
++ __u8 proximity_domain;
++ __u8 apic_id;
+ struct {
+- u32 enabled:1;
+- u32 reserved:31;
++ __u32 enabled:1;
++ __u32 reserved:31;
+ } flags;
+- u8 lsapic_eid;
+- u8 reserved[7];
++ __u8 lsapic_eid;
++ __u8 reserved[7];
+ } __attribute__ ((packed));
+
+ struct acpi_table_memory_affinity {
+ acpi_table_entry_header header;
+- u8 proximity_domain;
+- u8 reserved1[5];
+- u32 base_addr_lo;
+- u32 base_addr_hi;
+- u32 length_lo;
+- u32 length_hi;
+- u32 memory_type; /* See acpi_address_range_id */
++ __u8 proximity_domain;
++ __u8 reserved1[5];
++ __u32 base_addr_lo;
++ __u32 base_addr_hi;
++ __u32 length_lo;
++ __u32 length_hi;
++ __u32 memory_type; /* See acpi_address_range_id */
+ struct {
+- u32 enabled:1;
+- u32 hot_pluggable:1;
+- u32 reserved:30;
++ __u32 enabled:1;
++ __u32 hot_pluggable:1;
++ __u32 reserved:30;
+ } flags;
+- u64 reserved2;
++ __u64 reserved2;
+ } __attribute__ ((packed));
+
+ enum acpi_address_range_id {
+@@ -310,17 +310,17 @@
+
+ struct acpi_table_slit {
+ struct acpi_table_header header;
+- u64 localities;
+- u8 entry[1]; /* real size = localities^2 */
++ __u64 localities;
++ __u8 entry[1]; /* real size = localities^2 */
+ } __attribute__ ((packed));
+
+ /* Smart Battery Description Table (SBST) */
+
+ struct acpi_table_sbst {
+ struct acpi_table_header header;
+- u32 warning; /* Warn user */
+- u32 low; /* Critical sleep */
+- u32 critical; /* Critical shutdown */
++ __u32 warning; /* Warn user */
++ __u32 low; /* Critical sleep */
++ __u32 critical; /* Critical shutdown */
+ } __attribute__ ((packed));
+
+ /* Embedded Controller Boot Resources Table (ECDT) */
+@@ -329,8 +329,8 @@
+ struct acpi_table_header header;
+ struct acpi_generic_address ec_control;
+ struct acpi_generic_address ec_data;
+- u32 uid;
+- u8 gpe_bit;
++ __u32 uid;
++ __u8 gpe_bit;
+ char ec_id[0];
+ } __attribute__ ((packed));
+
+@@ -338,9 +338,9 @@
+
+ struct acpi_table_mcfg {
+ struct acpi_table_header header;
+- u8 reserved[8];
+- u32 base_address;
+- u32 base_reserved;
++ __u8 reserved[8];
++ __u32 base_address;
++ __u32 base_reserved;
+ } __attribute__ ((packed));
+
+ /* Table Handlers */
+@@ -396,7 +396,7 @@
+
+ extern int acpi_mp_config;
+
+-extern u32 pci_mmcfg_base_addr;
++extern __u32 pci_mmcfg_base_addr;
+
+ extern int sbf_port ;
+
+@@ -411,20 +411,20 @@
+
+ #endif /*!CONFIG_ACPI_BOOT*/
+
+-unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
+-int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
++unsigned int acpi_register_gsi (__u32 gsi, int edge_level, int active_high_low);
++int acpi_gsi_to_irq (__u32 gsi, unsigned int *irq);
+
+ #ifdef CONFIG_ACPI_PCI
+
+ struct acpi_prt_entry {
+ struct list_head node;
+ struct acpi_pci_id id;
+- u8 pin;
++ __u8 pin;
+ struct {
+ acpi_handle handle;
+- u32 index;
++ __u32 index;
+ } link;
+- u32 irq;
++ __u32 irq;
+ };
+
+ struct acpi_prt_list {
+@@ -451,8 +451,8 @@
+
+ #ifdef CONFIG_ACPI_EC
+
+-int ec_read(u8 addr, u8 *val);
+-int ec_write(u8 addr, u8 val);
++int ec_read(__u8 addr, __u8 *val);
++int ec_write(__u8 addr, __u8 val);
+
+ #endif /*CONFIG_ACPI_EC*/
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/affs_fs_i.h linux-libc-headers-2.6.8.0/include/linux/affs_fs_i.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/affs_fs_i.h 2003-12-31 17:46:48.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/affs_fs_i.h 2004-08-26 05:41:49.000000000 -0500
+@@ -9,13 +9,13 @@
+ //#define AFFS_CACHE_SIZE (4*4)
+
+ #define AFFS_MAX_PREALLOC 32
+-#define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2)
++#define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(__u32)/2)
+ #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2)
+ #define AFFS_AC_MASK (AFFS_AC_SIZE-1)
+
+ struct affs_ext_key {
+- u32 ext; /* idx of the extended block */
+- u32 key; /* block number */
++ __u32 ext; /* idx of the extended block */
++ __u32 key; /* block number */
+ };
+
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/affs_fs_sb.h linux-libc-headers-2.6.8.0/include/linux/affs_fs_sb.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/affs_fs_sb.h 2004-08-18 13:16:01.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/affs_fs_sb.h 2004-08-26 05:41:49.000000000 -0500
+@@ -9,8 +9,8 @@
+ */
+
+ struct affs_bm_info {
+- u32 bm_key; /* Disk block number */
+- u32 bm_free; /* Free blocks in here */
++ __u32 bm_key; /* Disk block number */
++ __u32 bm_free; /* Free blocks in here */
+ };
+
+ #define SF_INTL 0x0001 /* International filesystem. */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/affs_hardblocks.h linux-libc-headers-2.6.8.0/include/linux/affs_hardblocks.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/affs_hardblocks.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/affs_hardblocks.h 2004-08-26 05:41:49.000000000 -0500
+@@ -4,59 +4,59 @@
+ /* Just the needed definitions for the RDB of an Amiga HD. */
+
+ struct RigidDiskBlock {
+- u32 rdb_ID;
+- u32 rdb_SummedLongs;
+- s32 rdb_ChkSum;
+- u32 rdb_HostID;
+- u32 rdb_BlockBytes;
+- u32 rdb_Flags;
+- u32 rdb_BadBlockList;
+- u32 rdb_PartitionList;
+- u32 rdb_FileSysHeaderList;
+- u32 rdb_DriveInit;
+- u32 rdb_Reserved1[6];
+- u32 rdb_Cylinders;
+- u32 rdb_Sectors;
+- u32 rdb_Heads;
+- u32 rdb_Interleave;
+- u32 rdb_Park;
+- u32 rdb_Reserved2[3];
+- u32 rdb_WritePreComp;
+- u32 rdb_ReducedWrite;
+- u32 rdb_StepRate;
+- u32 rdb_Reserved3[5];
+- u32 rdb_RDBBlocksLo;
+- u32 rdb_RDBBlocksHi;
+- u32 rdb_LoCylinder;
+- u32 rdb_HiCylinder;
+- u32 rdb_CylBlocks;
+- u32 rdb_AutoParkSeconds;
+- u32 rdb_HighRDSKBlock;
+- u32 rdb_Reserved4;
++ __u32 rdb_ID;
++ __u32 rdb_SummedLongs;
++ __s32 rdb_ChkSum;
++ __u32 rdb_HostID;
++ __u32 rdb_BlockBytes;
++ __u32 rdb_Flags;
++ __u32 rdb_BadBlockList;
++ __u32 rdb_PartitionList;
++ __u32 rdb_FileSysHeaderList;
++ __u32 rdb_DriveInit;
++ __u32 rdb_Reserved1[6];
++ __u32 rdb_Cylinders;
++ __u32 rdb_Sectors;
++ __u32 rdb_Heads;
++ __u32 rdb_Interleave;
++ __u32 rdb_Park;
++ __u32 rdb_Reserved2[3];
++ __u32 rdb_WritePreComp;
++ __u32 rdb_ReducedWrite;
++ __u32 rdb_StepRate;
++ __u32 rdb_Reserved3[5];
++ __u32 rdb_RDBBlocksLo;
++ __u32 rdb_RDBBlocksHi;
++ __u32 rdb_LoCylinder;
++ __u32 rdb_HiCylinder;
++ __u32 rdb_CylBlocks;
++ __u32 rdb_AutoParkSeconds;
++ __u32 rdb_HighRDSKBlock;
++ __u32 rdb_Reserved4;
+ char rdb_DiskVendor[8];
+ char rdb_DiskProduct[16];
+ char rdb_DiskRevision[4];
+ char rdb_ControllerVendor[8];
+ char rdb_ControllerProduct[16];
+ char rdb_ControllerRevision[4];
+- u32 rdb_Reserved5[10];
++ __u32 rdb_Reserved5[10];
+ };
+
+ #define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */
+
+ struct PartitionBlock {
+- u32 pb_ID;
+- u32 pb_SummedLongs;
+- s32 pb_ChkSum;
+- u32 pb_HostID;
+- u32 pb_Next;
+- u32 pb_Flags;
+- u32 pb_Reserved1[2];
+- u32 pb_DevFlags;
+- u8 pb_DriveName[32];
+- u32 pb_Reserved2[15];
+- u32 pb_Environment[17];
+- u32 pb_EReserved[15];
++ __u32 pb_ID;
++ __u32 pb_SummedLongs;
++ __s32 pb_ChkSum;
++ __u32 pb_HostID;
++ __u32 pb_Next;
++ __u32 pb_Flags;
++ __u32 pb_Reserved1[2];
++ __u32 pb_DevFlags;
++ __u8 pb_DriveName[32];
++ __u32 pb_Reserved2[15];
++ __u32 pb_Environment[17];
++ __u32 pb_EReserved[15];
+ };
+
+ #define IDNAME_PARTITION 0x50415254 /* "PART" */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/amigaffs.h linux-libc-headers-2.6.8.0/include/linux/amigaffs.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/amigaffs.h 2003-12-31 17:46:48.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/amigaffs.h 2004-08-26 05:41:49.000000000 -0500
+@@ -64,90 +64,90 @@
+ #define AFFS_DATA(bh) (((struct affs_data_head *)(bh)->b_data)->data)
+
+ struct affs_date {
+- u32 days;
+- u32 mins;
+- u32 ticks;
++ __u32 days;
++ __u32 mins;
++ __u32 ticks;
+ };
+
+ struct affs_short_date {
+- u16 days;
+- u16 mins;
+- u16 ticks;
++ __u16 days;
++ __u16 mins;
++ __u16 ticks;
+ };
+
+ struct affs_root_head {
+- u32 ptype;
+- u32 spare1;
+- u32 spare2;
+- u32 hash_size;
+- u32 spare3;
+- u32 checksum;
+- u32 hashtable[1];
++ __u32 ptype;
++ __u32 spare1;
++ __u32 spare2;
++ __u32 hash_size;
++ __u32 spare3;
++ __u32 checksum;
++ __u32 hashtable[1];
+ };
+
+ struct affs_root_tail {
+- u32 bm_flag;
+- u32 bm_blk[AFFS_ROOT_BMAPS];
+- u32 bm_ext;
++ __u32 bm_flag;
++ __u32 bm_blk[AFFS_ROOT_BMAPS];
++ __u32 bm_ext;
+ struct affs_date root_change;
+- u8 disk_name[32];
+- u32 spare1;
+- u32 spare2;
++ __u8 disk_name[32];
++ __u32 spare1;
++ __u32 spare2;
+ struct affs_date disk_change;
+ struct affs_date disk_create;
+- u32 spare3;
+- u32 spare4;
+- u32 dcache;
+- u32 stype;
++ __u32 spare3;
++ __u32 spare4;
++ __u32 dcache;
++ __u32 stype;
+ };
+
+ struct affs_head {
+- u32 ptype;
+- u32 key;
+- u32 block_count;
+- u32 spare1;
+- u32 first_data;
+- u32 checksum;
+- u32 table[1];
++ __u32 ptype;
++ __u32 key;
++ __u32 block_count;
++ __u32 spare1;
++ __u32 first_data;
++ __u32 checksum;
++ __u32 table[1];
+ };
+
+ struct affs_tail {
+- u32 spare1;
+- u16 uid;
+- u16 gid;
+- u32 protect;
+- u32 size;
+- u8 comment[92];
++ __u32 spare1;
++ __u16 uid;
++ __u16 gid;
++ __u32 protect;
++ __u32 size;
++ __u8 comment[92];
+ struct affs_date change;
+- u8 name[32];
+- u32 spare2;
+- u32 original;
+- u32 link_chain;
+- u32 spare[5];
+- u32 hash_chain;
+- u32 parent;
+- u32 extension;
+- u32 stype;
++ __u8 name[32];
++ __u32 spare2;
++ __u32 original;
++ __u32 link_chain;
++ __u32 spare[5];
++ __u32 hash_chain;
++ __u32 parent;
++ __u32 extension;
++ __u32 stype;
+ };
+
+ struct slink_front
+ {
+- u32 ptype;
+- u32 key;
+- u32 spare1[3];
+- u32 checksum;
+- u8 symname[1]; /* depends on block size */
++ __u32 ptype;
++ __u32 key;
++ __u32 spare1[3];
++ __u32 checksum;
++ __u8 symname[1]; /* depends on block size */
+ };
+
+ struct affs_data_head
+ {
+- u32 ptype;
+- u32 key;
+- u32 sequence;
+- u32 size;
+- u32 next;
+- u32 checksum;
+- u8 data[1]; /* depends on block size */
++ __u32 ptype;
++ __u32 key;
++ __u32 sequence;
++ __u32 size;
++ __u32 next;
++ __u32 checksum;
++ __u8 data[1]; /* depends on block size */
+ };
+
+ /* Permission bits */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/ata.h linux-libc-headers-2.6.8.0/include/linux/ata.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/ata.h 2004-08-18 13:16:01.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/ata.h 2004-08-26 05:41:49.000000000 -0500
+@@ -34,7 +34,7 @@
+ ATA_MAX_PRD = 256, /* we could make these 256/256 */
+ ATA_SECT_SIZE = 512,
+ ATA_SECT_SIZE_MASK = (ATA_SECT_SIZE - 1),
+- ATA_SECT_DWORDS = ATA_SECT_SIZE / sizeof(u32),
++ ATA_SECT_DWORDS = ATA_SECT_SIZE / sizeof(__u32),
+
+ ATA_ID_WORDS = 256,
+ ATA_ID_PROD_OFS = 27,
+@@ -176,31 +176,31 @@
+ /* core structures */
+
+ struct ata_prd {
+- u32 addr;
+- u32 flags_len;
++ __u32 addr;
++ __u32 flags_len;
+ } __attribute__((packed));
+
+ struct ata_taskfile {
+ unsigned long flags; /* ATA_TFLAG_xxx */
+- u8 protocol; /* ATA_PROT_xxx */
++ __u8 protocol; /* ATA_PROT_xxx */
+
+- u8 ctl; /* control reg */
++ __u8 ctl; /* control reg */
+
+- u8 hob_feature; /* additional data */
+- u8 hob_nsect; /* to support LBA48 */
+- u8 hob_lbal;
+- u8 hob_lbam;
+- u8 hob_lbah;
++ __u8 hob_feature; /* additional data */
++ __u8 hob_nsect; /* to support LBA48 */
++ __u8 hob_lbal;
++ __u8 hob_lbam;
++ __u8 hob_lbah;
+
+- u8 feature;
+- u8 nsect;
+- u8 lbal;
+- u8 lbam;
+- u8 lbah;
++ __u8 feature;
++ __u8 nsect;
++ __u8 lbal;
++ __u8 lbam;
++ __u8 lbah;
+
+- u8 device;
++ __u8 device;
+
+- u8 command; /* IO operation */
++ __u8 command; /* IO operation */
+ };
+
+ #define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0)
+@@ -213,12 +213,12 @@
+ #define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 8))
+ #define ata_id_removeable(dev) ((dev)->id[0] & (1 << 7))
+ #define ata_id_u32(dev,n) \
+- (((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
++ (((__u32) (dev)->id[(n) + 1] << 16) | ((__u32) (dev)->id[(n)]))
+ #define ata_id_u64(dev,n) \
+- ( ((u64) dev->id[(n) + 3] << 48) | \
+- ((u64) dev->id[(n) + 2] << 32) | \
+- ((u64) dev->id[(n) + 1] << 16) | \
+- ((u64) dev->id[(n) + 0]) )
++ ( ((__u64) dev->id[(n) + 3] << 48) | \
++ ((__u64) dev->id[(n) + 2] << 32) | \
++ ((__u64) dev->id[(n) + 1] << 16) | \
++ ((__u64) dev->id[(n) + 0]) )
+
+ static inline int is_atapi_taskfile(struct ata_taskfile *tf)
+ {
+@@ -226,7 +226,7 @@
+ (tf->protocol == ATA_PROT_ATAPI_DMA);
+ }
+
+-static inline int ata_ok(u8 status)
++static inline int ata_ok(__u8 status)
+ {
+ return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
+ == ATA_DRDY);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/bitops.h linux-libc-headers-2.6.8.0/include/linux/bitops.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/bitops.h 2004-06-09 07:00:49.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/bitops.h 2004-08-26 05:41:49.000000000 -0500
+@@ -114,7 +114,7 @@
+ return generic_hweight32((unsigned int)(w >> 32)) +
+ generic_hweight32((unsigned int)w);
+ #else
+- u64 res;
++ __u64 res;
+ res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
+ res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+ res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/compat.h linux-libc-headers-2.6.8.0/include/linux/compat.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/compat.h 2004-06-09 07:00:49.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/compat.h 2004-08-26 05:41:49.000000000 -0500
+@@ -78,9 +78,9 @@
+ };
+
+ struct compat_dirent {
+- u32 d_ino;
++ __u32 d_ino;
+ compat_off_t d_off;
+- u16 d_reclen;
++ __u16 d_reclen;
+ char d_name[256];
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/console.h linux-libc-headers-2.6.8.0/include/linux/console.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/console.h 2004-08-18 13:16:02.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/console.h 2004-08-26 05:41:49.000000000 -0500
+@@ -49,9 +49,9 @@
+ int (*con_scrolldelta)(struct vc_data *, int);
+ int (*con_set_origin)(struct vc_data *);
+ void (*con_save_screen)(struct vc_data *);
+- u8 (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8);
+- void (*con_invert_region)(struct vc_data *, u16 *, int);
+- u16 *(*con_screen_pos)(struct vc_data *, int);
++ __u8 (*con_build_attr)(struct vc_data *, __u8, __u8, __u8, __u8, __u8);
++ void (*con_invert_region)(struct vc_data *, __u16 *, int);
++ __u16 *(*con_screen_pos)(struct vc_data *, int);
+ unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/cpufreq.h linux-libc-headers-2.6.8.0/include/linux/cpufreq.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/cpufreq.h 2004-06-23 16:52:53.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/cpufreq.h 2004-08-26 05:41:49.000000000 -0500
+@@ -103,7 +103,7 @@
+ unsigned int cpu; /* cpu nr */
+ unsigned int old;
+ unsigned int new;
+- u8 flags; /* flags of cpufreq_driver, see below. */
++ __u8 flags; /* flags of cpufreq_driver, see below. */
+ };
+
+
+@@ -120,13 +120,13 @@
+ {
+ #if BITS_PER_LONG == 32
+
+- u64 result = ((u64) old) * ((u64) mult);
++ __u64 result = ((__u64) old) * ((__u64) mult);
+ do_div(result, div);
+ return (unsigned long) result;
+
+ #elif BITS_PER_LONG == 64
+
+- unsigned long result = old * ((u64) mult);
++ unsigned long result = old * ((__u64) mult);
+ result /= div;
+ return result;
+
+@@ -178,7 +178,7 @@
+ struct cpufreq_driver {
+ struct module *owner;
+ char name[CPUFREQ_NAME_LEN];
+- u8 flags;
++ __u8 flags;
+
+ /* needed by all drivers */
+ int (*init) (struct cpufreq_policy *policy);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/cramfs_fs.h linux-libc-headers-2.6.8.0/include/linux/cramfs_fs.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/cramfs_fs.h 2004-01-05 12:42:27.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/cramfs_fs.h 2004-08-26 05:41:49.000000000 -0500
+@@ -2,9 +2,9 @@
+ #define __CRAMFS_H
+
+
+-typedef unsigned char u8;
+-typedef unsigned short u16;
+-typedef unsigned int u32;
++typedef unsigned char __u8;
++typedef unsigned short __u16;
++typedef unsigned int __u32;
+
+
+ #define CRAMFS_MAGIC 0x28cd3d45 /* some random number */
+@@ -31,9 +31,9 @@
+ * Reasonably terse representation of the inode data.
+ */
+ struct cramfs_inode {
+- u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
++ __u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
+ /* SIZE for device files is i_rdev */
+- u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
++ __u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
+ /* NAMELEN is the length of the file name, divided by 4 and
+ rounded up. (cramfs doesn't support hard links.) */
+ /* OFFSET: For symlinks and non-empty regular files, this
+@@ -42,27 +42,27 @@
+ see README). For non-empty directories it is the offset
+ (divided by 4) of the inode of the first file in that
+ directory. For anything else, offset is zero. */
+- u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
++ __u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
+ };
+
+ struct cramfs_info {
+- u32 crc;
+- u32 edition;
+- u32 blocks;
+- u32 files;
++ __u32 crc;
++ __u32 edition;
++ __u32 blocks;
++ __u32 files;
+ };
+
+ /*
+ * Superblock information at the beginning of the FS.
+ */
+ struct cramfs_super {
+- u32 magic; /* 0x28cd3d45 - random number */
+- u32 size; /* length in bytes */
+- u32 flags; /* feature flags */
+- u32 future; /* reserved for future use */
+- u8 signature[16]; /* "Compressed ROMFS" */
++ __u32 magic; /* 0x28cd3d45 - random number */
++ __u32 size; /* length in bytes */
++ __u32 flags; /* feature flags */
++ __u32 future; /* reserved for future use */
++ __u8 signature[16]; /* "Compressed ROMFS" */
+ struct cramfs_info fsid; /* unique filesystem info */
+- u8 name[16]; /* user-defined name */
++ __u8 name[16]; /* user-defined name */
+ struct cramfs_inode root; /* root inode data */
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/crc32.h linux-libc-headers-2.6.8.0/include/linux/crc32.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/crc32.h 2003-12-15 12:46:57.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/crc32.h 2004-08-26 05:41:49.000000000 -0500
+@@ -7,9 +7,9 @@
+
+ #include <linux/types.h>
+
+-extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
+-extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len);
+-extern u32 bitreverse(u32 in);
++extern __u32 crc32_le(__u32 crc, unsigned char const *p, size_t len);
++extern __u32 crc32_be(__u32 crc, unsigned char const *p, size_t len);
++extern __u32 bitreverse(__u32 in);
+
+ #define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length)
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/crypto.h linux-libc-headers-2.6.8.0/include/linux/crypto.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/crypto.h 2004-04-19 16:13:51.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/crypto.h 2004-08-26 05:41:49.000000000 -0500
+@@ -63,28 +63,28 @@
+ struct cipher_alg {
+ unsigned int cia_min_keysize;
+ unsigned int cia_max_keysize;
+- int (*cia_setkey)(void *ctx, const u8 *key,
+- unsigned int keylen, u32 *flags);
+- void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
+- void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
++ int (*cia_setkey)(void *ctx, const __u8 *key,
++ unsigned int keylen, __u32 *flags);
++ void (*cia_encrypt)(void *ctx, __u8 *dst, const __u8 *src);
++ void (*cia_decrypt)(void *ctx, __u8 *dst, const __u8 *src);
+ };
+
+ struct digest_alg {
+ unsigned int dia_digestsize;
+ void (*dia_init)(void *ctx);
+- void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
+- void (*dia_final)(void *ctx, u8 *out);
+- int (*dia_setkey)(void *ctx, const u8 *key,
+- unsigned int keylen, u32 *flags);
++ void (*dia_update)(void *ctx, const __u8 *data, unsigned int len);
++ void (*dia_final)(void *ctx, __u8 *out);
++ int (*dia_setkey)(void *ctx, const __u8 *key,
++ unsigned int keylen, __u32 *flags);
+ };
+
+ struct compress_alg {
+ int (*coa_init)(void *ctx);
+ void (*coa_exit)(void *ctx);
+- int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
+- int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
++ int (*coa_compress)(void *ctx, const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen);
++ int (*coa_decompress)(void *ctx, const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen);
+ };
+
+ #define cra_cipher cra_u.cipher
+@@ -93,7 +93,7 @@
+
+ struct crypto_alg {
+ struct list_head cra_list;
+- u32 cra_flags;
++ __u32 cra_flags;
+ unsigned int cra_blocksize;
+ unsigned int cra_ctxsize;
+ const char cra_name[CRYPTO_MAX_ALG_NAME];
+@@ -116,7 +116,7 @@
+ /*
+ * Algorithm query interface.
+ */
+-int crypto_alg_available(const char *name, u32 flags);
++int crypto_alg_available(const char *name, __u32 flags);
+
+ /*
+ * Transforms: user-instantiated objects which encapsulate algorithms
+@@ -128,9 +128,9 @@
+ struct cipher_tfm {
+ void *cit_iv;
+ unsigned int cit_ivsize;
+- u32 cit_mode;
++ __u32 cit_mode;
+ int (*cit_setkey)(struct crypto_tfm *tfm,
+- const u8 *key, unsigned int keylen);
++ const __u8 *key, unsigned int keylen);
+ int (*cit_encrypt)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+@@ -138,7 +138,7 @@
+ int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+- unsigned int nbytes, u8 *iv);
++ unsigned int nbytes, __u8 *iv);
+ int (*cit_decrypt)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+@@ -146,19 +146,19 @@
+ int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+- unsigned int nbytes, u8 *iv);
+- void (*cit_xor_block)(u8 *dst, const u8 *src);
++ unsigned int nbytes, __u8 *iv);
++ void (*cit_xor_block)(__u8 *dst, const __u8 *src);
+ };
+
+ struct digest_tfm {
+ void (*dit_init)(struct crypto_tfm *tfm);
+ void (*dit_update)(struct crypto_tfm *tfm,
+ struct scatterlist *sg, unsigned int nsg);
+- void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
++ void (*dit_final)(struct crypto_tfm *tfm, __u8 *out);
+ void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
+- unsigned int nsg, u8 *out);
++ unsigned int nsg, __u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+- const u8 *key, unsigned int keylen);
++ const __u8 *key, unsigned int keylen);
+ #ifdef CONFIG_CRYPTO_HMAC
+ void *dit_hmac_block;
+ #endif
+@@ -166,11 +166,11 @@
+
+ struct compress_tfm {
+ int (*cot_compress)(struct crypto_tfm *tfm,
+- const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
++ const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen);
+ int (*cot_decompress)(struct crypto_tfm *tfm,
+- const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
++ const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen);
+ };
+
+ #define crt_cipher crt_u.cipher
+@@ -179,7 +179,7 @@
+
+ struct crypto_tfm {
+
+- u32 crt_flags;
++ __u32 crt_flags;
+
+ union {
+ struct cipher_tfm cipher;
+@@ -203,7 +203,7 @@
+ * crypto_free_tfm() frees up the transform and any associated resources,
+ * then drops the refcount on the associated algorithm.
+ */
+-struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
++struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, __u32 tfm_flags);
+ void crypto_free_tfm(struct crypto_tfm *tfm);
+
+ /*
+@@ -219,7 +219,7 @@
+ return module_name(tfm->__crt_alg->cra_module);
+ }
+
+-static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
++static inline __u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
+ {
+ return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
+ }
+@@ -270,7 +270,7 @@
+ tfm->crt_digest.dit_update(tfm, sg, nsg);
+ }
+
+-static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
++static inline void crypto_digest_final(struct crypto_tfm *tfm, __u8 *out)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_final(tfm, out);
+@@ -278,14 +278,14 @@
+
+ static inline void crypto_digest_digest(struct crypto_tfm *tfm,
+ struct scatterlist *sg,
+- unsigned int nsg, u8 *out)
++ unsigned int nsg, __u8 *out)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+ }
+
+ static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+- const u8 *key, unsigned int keylen)
++ const __u8 *key, unsigned int keylen)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+@@ -294,7 +294,7 @@
+ }
+
+ static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
+- const u8 *key, unsigned int keylen)
++ const __u8 *key, unsigned int keylen)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
+@@ -312,7 +312,7 @@
+ static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+- unsigned int nbytes, u8 *iv)
++ unsigned int nbytes, __u8 *iv)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+@@ -331,7 +331,7 @@
+ static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+- unsigned int nbytes, u8 *iv)
++ unsigned int nbytes, __u8 *iv)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+@@ -339,30 +339,30 @@
+ }
+
+ static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
+- const u8 *src, unsigned int len)
++ const __u8 *src, unsigned int len)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ memcpy(tfm->crt_cipher.cit_iv, src, len);
+ }
+
+ static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
+- u8 *dst, unsigned int len)
++ __u8 *dst, unsigned int len)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ memcpy(dst, tfm->crt_cipher.cit_iv, len);
+ }
+
+ static inline int crypto_comp_compress(struct crypto_tfm *tfm,
+- const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen)
++ const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+ return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
+ }
+
+ static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
+- const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen)
++ const __u8 *src, unsigned int slen,
++ __u8 *dst, unsigned int *dlen)
+ {
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+ return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
+@@ -372,13 +372,13 @@
+ * HMAC support.
+ */
+ #ifdef CONFIG_CRYPTO_HMAC
+-void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
++void crypto_hmac_init(struct crypto_tfm *tfm, __u8 *key, unsigned int *keylen);
+ void crypto_hmac_update(struct crypto_tfm *tfm,
+ struct scatterlist *sg, unsigned int nsg);
+-void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
+- unsigned int *keylen, u8 *out);
+-void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
+- struct scatterlist *sg, unsigned int nsg, u8 *out);
++void crypto_hmac_final(struct crypto_tfm *tfm, __u8 *key,
++ unsigned int *keylen, __u8 *out);
++void crypto_hmac(struct crypto_tfm *tfm, __u8 *key, unsigned int *keylen,
++ struct scatterlist *sg, unsigned int nsg, __u8 *out);
+ #endif /* CONFIG_CRYPTO_HMAC */
+
+ #endif /* _LINUX_CRYPTO_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/cycx_drv.h linux-libc-headers-2.6.8.0/include/linux/cycx_drv.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/cycx_drv.h 2003-12-15 12:46:57.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/cycx_drv.h 2004-08-26 05:41:49.000000000 -0500
+@@ -14,9 +14,9 @@
+ * ============================================================================
+ * 1999/10/23 acme cycxhw_t cleanup
+ * 1999/01/03 acme more judicious use of data types...
+-* uclong, ucchar, etc deleted, the u8, u16, u32
++* uclong, ucchar, etc deleted, the __u8, __u16, __u32
+ * types are the portable way to go.
+-* 1999/01/03 acme judicious use of data types... u16, u32, etc
++* 1999/01/03 acme judicious use of data types... __u16, __u32, etc
+ * 1998/12/26 acme FIXED_BUFFERS, CONF_OFFSET,
+ * removal of cy_read{bwl}
+ * 1998/08/08 acme Initial version.
+@@ -46,18 +46,18 @@
+ * @reserved - reserved for future use
+ */
+ struct cycx_hw {
+- u32 fwid;
++ __u32 fwid;
+ int irq;
+ void *dpmbase;
+- u32 dpmsize;
+- u32 reserved[5];
++ __u32 dpmsize;
++ __u32 reserved[5];
+ };
+
+ /* Function Prototypes */
+-extern int cycx_setup(struct cycx_hw *hw, void *sfm, u32 len);
++extern int cycx_setup(struct cycx_hw *hw, void *sfm, __u32 len);
+ extern int cycx_down(struct cycx_hw *hw);
+-extern int cycx_peek(struct cycx_hw *hw, u32 addr, void *buf, u32 len);
+-extern int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len);
++extern int cycx_peek(struct cycx_hw *hw, __u32 addr, void *buf, __u32 len);
++extern int cycx_poke(struct cycx_hw *hw, __u32 addr, void *buf, __u32 len);
+ extern int cycx_exec(void *addr);
+
+ extern void cycx_inten(struct cycx_hw *hw);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/cycx_x25.h linux-libc-headers-2.6.8.0/include/linux/cycx_x25.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/cycx_x25.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/cycx_x25.h 2004-08-26 05:41:49.000000000 -0500
+@@ -38,10 +38,10 @@
+ /* Data Structures */
+ /* X.25 Command Block. */
+ struct cycx_x25_cmd {
+- u16 command PACKED;
+- u16 link PACKED; /* values: 0 or 1 */
+- u16 len PACKED; /* values: 0 thru 0x205 (517) */
+- u32 buf PACKED;
++ __u16 command PACKED;
++ __u16 link PACKED; /* values: 0 or 1 */
++ __u16 len PACKED; /* values: 0 thru 0x205 (517) */
++ __u32 buf PACKED;
+ };
+
+ /* Defines for the 'command' field. */
+@@ -92,34 +92,34 @@
+ * @flags - see dosx25.doc, in portuguese, for details
+ */
+ struct cycx_x25_config {
+- u8 link PACKED;
+- u8 speed PACKED;
+- u8 clock PACKED;
+- u8 n2 PACKED;
+- u8 n2win PACKED;
+- u8 n3win PACKED;
+- u8 nvc PACKED;
+- u8 pktlen PACKED;
+- u8 locaddr PACKED;
+- u8 remaddr PACKED;
+- u16 t1 PACKED;
+- u16 t2 PACKED;
+- u8 t21 PACKED;
+- u8 npvc PACKED;
+- u8 t23 PACKED;
+- u8 flags PACKED;
++ __u8 link PACKED;
++ __u8 speed PACKED;
++ __u8 clock PACKED;
++ __u8 n2 PACKED;
++ __u8 n2win PACKED;
++ __u8 n3win PACKED;
++ __u8 nvc PACKED;
++ __u8 pktlen PACKED;
++ __u8 locaddr PACKED;
++ __u8 remaddr PACKED;
++ __u16 t1 PACKED;
++ __u16 t2 PACKED;
++ __u8 t21 PACKED;
++ __u8 npvc PACKED;
++ __u8 t23 PACKED;
++ __u8 flags PACKED;
+ };
+
+ struct cycx_x25_stats {
+- u16 rx_crc_errors PACKED;
+- u16 rx_over_errors PACKED;
+- u16 n2_tx_frames PACKED;
+- u16 n2_rx_frames PACKED;
+- u16 tx_timeouts PACKED;
+- u16 rx_timeouts PACKED;
+- u16 n3_tx_packets PACKED;
+- u16 n3_rx_packets PACKED;
+- u16 tx_aborts PACKED;
+- u16 rx_aborts PACKED;
++ __u16 rx_crc_errors PACKED;
++ __u16 rx_over_errors PACKED;
++ __u16 n2_tx_frames PACKED;
++ __u16 n2_rx_frames PACKED;
++ __u16 tx_timeouts PACKED;
++ __u16 rx_timeouts PACKED;
++ __u16 n3_tx_packets PACKED;
++ __u16 n3_rx_packets PACKED;
++ __u16 tx_aborts PACKED;
++ __u16 rx_aborts PACKED;
+ };
+ #endif /* _CYCX_X25_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/device.h linux-libc-headers-2.6.8.0/include/linux/device.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/device.h 2004-08-18 13:16:02.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/device.h 2004-08-26 05:41:49.000000000 -0500
+@@ -57,7 +57,7 @@
+ struct device * (*add) (struct device * parent, char * bus_id);
+ int (*hotplug) (struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
+- int (*suspend)(struct device * dev, u32 state);
++ int (*suspend)(struct device * dev, __u32 state);
+ int (*resume)(struct device * dev);
+ };
+
+@@ -105,8 +105,8 @@
+ int (*probe) (struct device * dev);
+ int (*remove) (struct device * dev);
+ void (*shutdown) (struct device * dev);
+- int (*suspend) (struct device * dev, u32 state, u32 level);
+- int (*resume) (struct device * dev, u32 level);
++ int (*suspend) (struct device * dev, __u32 state, __u32 level);
++ int (*resume) (struct device * dev, __u32 level);
+ };
+
+
+@@ -262,17 +262,17 @@
+ void *platform_data; /* Platform specific data (e.g. ACPI,
+ BIOS data relevant to device) */
+ struct dev_pm_info power;
+- u32 power_state; /* Current operating state. In
++ __u32 power_state; /* Current operating state. In
+ ACPI-speak, this is D0-D3, D0
+ being fully functional, and D3
+ being off. */
+
+ unsigned char *saved_state; /* saved device state */
+- u32 detach_state; /* State to enter when device is
++ __u32 detach_state; /* State to enter when device is
+ detached from its driver. */
+
+- u64 *dma_mask; /* dma mask (if dma'able device) */
+- u64 coherent_dma_mask;/* Like dma_mask, but for
++ __u64 *dma_mask; /* dma mask (if dma'able device) */
++ __u64 coherent_dma_mask;/* Like dma_mask, but for
+ alloc_coherent mappings as
+ not all hardware supports
+ 64 bit addresses for consistent
+@@ -360,9 +360,9 @@
+
+ struct platform_device {
+ char * name;
+- u32 id;
++ __u32 id;
+ struct device dev;
+- u32 num_resources;
++ __u32 num_resources;
+ struct resource * resource;
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/divert.h linux-libc-headers-2.6.8.0/include/linux/divert.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/divert.h 2004-06-09 07:00:49.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/divert.h 2004-08-26 05:41:49.000000000 -0500
+@@ -27,10 +27,10 @@
+ {
+ int divert; /* are we active */
+ unsigned int protos; /* protocols */
+- u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
+- u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
+- u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
+- u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
++ __u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
++ __u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
++ __u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
++ __u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
+ };
+
+ /*
+@@ -40,12 +40,12 @@
+
+ typedef union _divert_cf_arg
+ {
+- s16 int16;
+- u16 uint16;
+- s32 int32;
+- u32 uint32;
+- s64 int64;
+- u64 uint64;
++ __s16 int16;
++ __u16 uint16;
++ __s32 int32;
++ __u32 uint32;
++ __s64 int64;
++ __u64 uint64;
+ void *ptr;
+ } divert_cf_arg;
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/eeprom.h linux-libc-headers-2.6.8.0/include/linux/eeprom.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/eeprom.h 2003-12-19 07:05:15.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/eeprom.h 2004-08-26 13:26:38.000000000 -0500
+@@ -26,15 +26,15 @@
+ unsigned ee_state;
+
+ spinlock_t *lock;
+- u32 *cache;
++ __u32 *cache;
+ };
+
+
+-u8 eeprom_readb(struct eeprom *ee, unsigned address);
+-void eeprom_read(struct eeprom *ee, unsigned address, u8 *bytes,
++__u8 eeprom_readb(struct eeprom *ee, unsigned address);
++void eeprom_read(struct eeprom *ee, unsigned address, __u8 *bytes,
+ unsigned count);
+-void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data);
+-void eeprom_write(struct eeprom *ee, unsigned address, u8 *bytes,
++void eeprom_writeb(struct eeprom *ee, unsigned address, __u8 data);
++void eeprom_write(struct eeprom *ee, unsigned address, __u8 *bytes,
+ unsigned count);
+
+ /* The EEPROM commands include the alway-set leading bit. */
+@@ -56,10 +56,10 @@
+ }
+
+ /* foo. put this in a .c file */
+-static inline void eeprom_update(struct eeprom *ee, u32 mask, int pol)
++static inline void eeprom_update(struct eeprom *ee, __u32 mask, int pol)
+ {
+ unsigned long flags;
+- u32 data;
++ __u32 data;
+
+ spin_lock_irqsave(ee->lock, flags);
+ data = *ee->cache;
+@@ -106,17 +106,17 @@
+ eeprom_update(ee, ee->eedi, pol);
+ }
+
+-u16 eeprom_readw(struct eeprom *ee, unsigned address)
++__u16 eeprom_readw(struct eeprom *ee, unsigned address)
+ {
+ unsigned i;
+- u16 res = 0;
++ __u16 res = 0;
+
+ eeprom_clk_lo(ee);
+ eeprom_update(ee, ee->eesel, 1 ^ !!(ee->polarity & EEPOL_EESEL));
+ eeprom_send_addr(ee, address);
+
+ for (i=0; i<16; i++) {
+- u32 data;
++ __u32 data;
+ eeprom_clk_hi(ee);
+ res <<= 1;
+ data = readl(ee->addr);
+@@ -130,6 +130,6 @@
+ }
+
+
+-void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data)
++void eeprom_writeb(struct eeprom *ee, unsigned address, __u8 data)
+ {
+ }
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/efi.h linux-libc-headers-2.6.8.0/include/linux/efi.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/efi.h 2004-08-18 13:16:02.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/efi.h 2004-08-26 05:42:08.000000000 -0500
+@@ -30,12 +30,12 @@
+ #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
+
+ typedef unsigned long efi_status_t;
+-typedef u8 efi_bool_t;
+-typedef u16 efi_char16_t; /* UNICODE character */
++typedef __u8 efi_bool_t;
++typedef __u16 efi_char16_t; /* UNICODE character */
+
+
+ typedef struct {
+- u8 b[16];
++ __u8 b[16];
+ } efi_guid_t;
+
+ #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+@@ -49,11 +49,11 @@
+ * Generic EFI table header
+ */
+ typedef struct {
+- u64 signature;
+- u32 revision;
+- u32 headersize;
+- u32 crc32;
+- u32 reserved;
++ __u64 signature;
++ __u32 revision;
++ __u32 headersize;
++ __u32 crc32;
++ __u32 reserved;
+ } efi_table_hdr_t;
+
+ /*
+@@ -78,14 +78,14 @@
+ #define EFI_MAX_MEMORY_TYPE 14
+
+ /* Attribute values: */
+-#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
+-#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
+-#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
+-#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
+-#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
+-#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
+-#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
+-#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
++#define EFI_MEMORY_UC ((__u64)0x0000000000000001ULL) /* uncached */
++#define EFI_MEMORY_WC ((__u64)0x0000000000000002ULL) /* write-coalescing */
++#define EFI_MEMORY_WT ((__u64)0x0000000000000004ULL) /* write-through */
++#define EFI_MEMORY_WB ((__u64)0x0000000000000008ULL) /* write-back */
++#define EFI_MEMORY_WP ((__u64)0x0000000000001000ULL) /* write-protect */
++#define EFI_MEMORY_RP ((__u64)0x0000000000002000ULL) /* read-protect */
++#define EFI_MEMORY_XP ((__u64)0x0000000000004000ULL) /* execute-protect */
++#define EFI_MEMORY_RUNTIME ((__u64)0x8000000000000000ULL) /* range requires runtime mapping */
+ #define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+ #define EFI_PAGE_SHIFT 12
+@@ -96,14 +96,14 @@
+ * the case in ia64. Need to have this fixed in the f/w.
+ */
+ typedef struct {
+- u32 type;
+- u32 pad;
+- u64 phys_addr;
+- u64 virt_addr;
+- u64 num_pages;
+- u64 attribute;
++ __u32 type;
++ __u32 pad;
++ __u64 phys_addr;
++ __u64 virt_addr;
++ __u64 num_pages;
++ __u64 attribute;
+ #if defined (__i386__)
+- u64 pad1;
++ __u64 pad1;
+ #endif
+ } efi_memory_desc_t;
+
+@@ -117,23 +117,23 @@
+ #define EFI_UNSPECIFIED_TIMEZONE 0x07ff
+
+ typedef struct {
+- u16 year;
+- u8 month;
+- u8 day;
+- u8 hour;
+- u8 minute;
+- u8 second;
+- u8 pad1;
+- u32 nanosecond;
+- s16 timezone;
+- u8 daylight;
+- u8 pad2;
++ __u16 year;
++ __u8 month;
++ __u8 day;
++ __u8 hour;
++ __u8 minute;
++ __u8 second;
++ __u8 pad1;
++ __u32 nanosecond;
++ __s16 timezone;
++ __u8 daylight;
++ __u8 pad2;
+ } efi_time_t;
+
+ typedef struct {
+- u32 resolution;
+- u32 accuracy;
+- u8 sets_to_zero;
++ __u32 resolution;
++ __u32 accuracy;
++ __u8 sets_to_zero;
+ } efi_time_cap_t;
+
+ /*
+@@ -146,7 +146,7 @@
+ /*
+ * EFI Runtime Services table
+ */
+-#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
++#define EFI_RUNTIME_SERVICES_SIGNATURE ((__u64)0x5652453544e5552ULL)
+ #define EFI_RUNTIME_SERVICES_REVISION 0x00010000
+
+ typedef struct {
+@@ -169,19 +169,19 @@
+ typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
+ efi_time_t *tm);
+ typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
+-typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
++typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, __u32 *attr,
+ unsigned long *data_size, void *data);
+ typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
+ efi_guid_t *vendor);
+ typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
+ unsigned long attr, unsigned long data_size,
+ void *data);
+-typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
++typedef efi_status_t efi_get_next_high_mono_count_t (__u32 *count);
+ typedef void efi_reset_system_t (int reset_type, efi_status_t status,
+ unsigned long data_size, efi_char16_t *data);
+ typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
+ unsigned long descriptor_size,
+- u32 descriptor_version,
++ __u32 descriptor_version,
+ efi_memory_desc_t *virtual_map);
+
+ /*
+@@ -219,13 +219,13 @@
+ unsigned long table;
+ } efi_config_table_t;
+
+-#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
++#define EFI_SYSTEM_TABLE_SIGNATURE ((__u64)0x5453595320494249ULL)
+ #define EFI_SYSTEM_TABLE_REVISION ((1 << 16) | 00)
+
+ typedef struct {
+ efi_table_hdr_t hdr;
+ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
+- u32 fw_revision;
++ __u32 fw_revision;
+ unsigned long con_in_handle;
+ unsigned long con_in;
+ unsigned long con_out_handle;
+@@ -293,9 +293,9 @@
+ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
+ extern void efi_gettimeofday (struct timespec *ts);
+ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
+-extern u64 efi_get_iobase (void);
+-extern u32 efi_mem_type (unsigned long phys_addr);
+-extern u64 efi_mem_attributes (unsigned long phys_addr);
++extern __u64 efi_get_iobase (void);
++extern __u32 efi_mem_type (unsigned long phys_addr);
++extern __u64 efi_mem_attributes (unsigned long phys_addr);
+ extern int __init efi_uart_console_only (void);
+ extern void efi_initialize_iomem_resources(struct resource *code_resource,
+ struct resource *data_resource);
+@@ -368,9 +368,9 @@
+ #define EFI_DEV_END_ENTIRE 0xFF
+
+ struct efi_generic_dev_path {
+- u8 type;
+- u8 sub_type;
+- u16 length;
++ __u8 type;
++ __u8 sub_type;
++ __u16 length;
+ } __attribute ((packed));
+
+ #endif /* _LINUX_EFI_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/eisa.h linux-libc-headers-2.6.8.0/include/linux/eisa.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/eisa.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/eisa.h 2004-08-26 05:42:08.000000000 -0500
+@@ -43,7 +43,7 @@
+ int state;
+ unsigned long base_addr;
+ struct resource res[EISA_MAX_RESOURCES];
+- u64 dma_mask;
++ __u64 dma_mask;
+ struct device dev; /* generic device */
+ #ifdef CONFIG_EISA_NAMES
+ char pretty_name[DEVICE_NAME_SIZE];
+@@ -91,7 +91,7 @@
+ unsigned long bus_base_addr;
+ int slots; /* Max slot number */
+ int force_probe; /* Probe even when no slot 0 */
+- u64 dma_mask; /* from bridge device */
++ __u64 dma_mask; /* from bridge device */
+ int bus_nr; /* Set by eisa_root_register */
+ struct resource eisa_root_res; /* ditto */
+ };
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/ethtool.h linux-libc-headers-2.6.8.0/include/linux/ethtool.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/ethtool.h 2004-06-23 16:52:54.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/ethtool.h 2004-08-26 13:29:11.000000000 -0500
+@@ -15,24 +15,24 @@
+
+ /* This should work for both 32 and 64 bit userland. */
+ struct ethtool_cmd {
+- u32 cmd;
+- u32 supported; /* Features this interface supports */
+- u32 advertising; /* Features this interface advertises */
+- u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
+- u8 duplex; /* Duplex, half or full */
+- u8 port; /* Which connector port */
+- u8 phy_address;
+- u8 transceiver; /* Which transceiver to use */
+- u8 autoneg; /* Enable or disable autonegotiation */
+- u32 maxtxpkt; /* Tx pkts before generating tx int */
+- u32 maxrxpkt; /* Rx pkts before generating rx int */
+- u32 reserved[4];
++ __u32 cmd;
++ __u32 supported; /* Features this interface supports */
++ __u32 advertising; /* Features this interface advertises */
++ __u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
++ __u8 duplex; /* Duplex, half or full */
++ __u8 port; /* Which connector port */
++ __u8 phy_address;
++ __u8 transceiver; /* Which transceiver to use */
++ __u8 autoneg; /* Enable or disable autonegotiation */
++ __u32 maxtxpkt; /* Tx pkts before generating tx int */
++ __u32 maxrxpkt; /* Rx pkts before generating rx int */
++ __u32 reserved[4];
+ };
+
+ #define ETHTOOL_BUSINFO_LEN 32
+ /* these strings are set to whatever the driver author decides... */
+ struct ethtool_drvinfo {
+- u32 cmd;
++ __u32 cmd;
+ char driver[32]; /* driver short name, "tulip", "eepro100" */
+ char version[32]; /* driver version string */
+ char fw_version[32]; /* firmware version string, if applicable */
+@@ -40,53 +40,53 @@
+ /* For PCI devices, use pci_name(pci_dev). */
+ char reserved1[32];
+ char reserved2[16];
+- u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */
+- u32 testinfo_len;
+- u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
+- u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
++ __u32 n_stats; /* number of __u64's from ETHTOOL_GSTATS */
++ __u32 testinfo_len;
++ __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
++ __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
+ };
+
+ #define SOPASS_MAX 6
+ /* wake-on-lan settings */
+ struct ethtool_wolinfo {
+- u32 cmd;
+- u32 supported;
+- u32 wolopts;
+- u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */
++ __u32 cmd;
++ __u32 supported;
++ __u32 wolopts;
++ __u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+ };
+
+ /* for passing single values */
+ struct ethtool_value {
+- u32 cmd;
+- u32 data;
++ __u32 cmd;
++ __u32 data;
+ };
+
+ /* for passing big chunks of data */
+ struct ethtool_regs {
+- u32 cmd;
+- u32 version; /* driver-specific, indicates different chips/revs */
+- u32 len; /* bytes */
+- u8 data[0];
++ __u32 cmd;
++ __u32 version; /* driver-specific, indicates different chips/revs */
++ __u32 len; /* bytes */
++ __u8 data[0];
+ };
+
+ /* for passing EEPROM chunks */
+ struct ethtool_eeprom {
+- u32 cmd;
+- u32 magic;
+- u32 offset; /* in bytes */
+- u32 len; /* in bytes */
+- u8 data[0];
++ __u32 cmd;
++ __u32 magic;
++ __u32 offset; /* in bytes */
++ __u32 len; /* in bytes */
++ __u8 data[0];
+ };
+
+ /* for configuring coalescing parameters of chip */
+ struct ethtool_coalesce {
+- u32 cmd; /* ETHTOOL_{G,S}COALESCE */
++ __u32 cmd; /* ETHTOOL_{G,S}COALESCE */
+
+ /* How many usecs to delay an RX interrupt after
+ * a packet arrives. If 0, only rx_max_coalesced_frames
+ * is used.
+ */
+- u32 rx_coalesce_usecs;
++ __u32 rx_coalesce_usecs;
+
+ /* How many packets to delay an RX interrupt after
+ * a packet arrives. If 0, only rx_coalesce_usecs is
+@@ -94,21 +94,21 @@
+ * to zero as this would cause RX interrupts to never be
+ * generated.
+ */
+- u32 rx_max_coalesced_frames;
++ __u32 rx_max_coalesced_frames;
+
+ /* Same as above two parameters, except that these values
+ * apply while an IRQ is being serviced by the host. Not
+ * all cards support this feature and the values are ignored
+ * in that case.
+ */
+- u32 rx_coalesce_usecs_irq;
+- u32 rx_max_coalesced_frames_irq;
++ __u32 rx_coalesce_usecs_irq;
++ __u32 rx_max_coalesced_frames_irq;
+
+ /* How many usecs to delay a TX interrupt after
+ * a packet is sent. If 0, only tx_max_coalesced_frames
+ * is used.
+ */
+- u32 tx_coalesce_usecs;
++ __u32 tx_coalesce_usecs;
+
+ /* How many packets to delay a TX interrupt after
+ * a packet is sent. If 0, only tx_coalesce_usecs is
+@@ -116,22 +116,22 @@
+ * to zero as this would cause TX interrupts to never be
+ * generated.
+ */
+- u32 tx_max_coalesced_frames;
++ __u32 tx_max_coalesced_frames;
+
+ /* Same as above two parameters, except that these values
+ * apply while an IRQ is being serviced by the host. Not
+ * all cards support this feature and the values are ignored
+ * in that case.
+ */
+- u32 tx_coalesce_usecs_irq;
+- u32 tx_max_coalesced_frames_irq;
++ __u32 tx_coalesce_usecs_irq;
++ __u32 tx_max_coalesced_frames_irq;
+
+ /* How many usecs to delay in-memory statistics
+ * block updates. Some drivers do not have an in-memory
+ * statistic block, and in such cases this value is ignored.
+ * This value must not be zero.
+ */
+- u32 stats_block_coalesce_usecs;
++ __u32 stats_block_coalesce_usecs;
+
+ /* Adaptive RX/TX coalescing is an algorithm implemented by
+ * some drivers to improve latency under low packet rates and
+@@ -140,18 +140,18 @@
+ * not implemented by the driver causes these values to be
+ * silently ignored.
+ */
+- u32 use_adaptive_rx_coalesce;
+- u32 use_adaptive_tx_coalesce;
++ __u32 use_adaptive_rx_coalesce;
++ __u32 use_adaptive_tx_coalesce;
+
+ /* When the packet rate (measured in packets per second)
+ * is below pkt_rate_low, the {rx,tx}_*_low parameters are
+ * used.
+ */
+- u32 pkt_rate_low;
+- u32 rx_coalesce_usecs_low;
+- u32 rx_max_coalesced_frames_low;
+- u32 tx_coalesce_usecs_low;
+- u32 tx_max_coalesced_frames_low;
++ __u32 pkt_rate_low;
++ __u32 rx_coalesce_usecs_low;
++ __u32 rx_max_coalesced_frames_low;
++ __u32 tx_coalesce_usecs_low;
++ __u32 tx_max_coalesced_frames_low;
+
+ /* When the packet rate is below pkt_rate_high but above
+ * pkt_rate_low (both measured in packets per second) the
+@@ -162,43 +162,43 @@
+ * is above pkt_rate_high, the {rx,tx}_*_high parameters are
+ * used.
+ */
+- u32 pkt_rate_high;
+- u32 rx_coalesce_usecs_high;
+- u32 rx_max_coalesced_frames_high;
+- u32 tx_coalesce_usecs_high;
+- u32 tx_max_coalesced_frames_high;
++ __u32 pkt_rate_high;
++ __u32 rx_coalesce_usecs_high;
++ __u32 rx_max_coalesced_frames_high;
++ __u32 tx_coalesce_usecs_high;
++ __u32 tx_max_coalesced_frames_high;
+
+ /* How often to do adaptive coalescing packet rate sampling,
+ * measured in seconds. Must not be zero.
+ */
+- u32 rate_sample_interval;
++ __u32 rate_sample_interval;
+ };
+
+ /* for configuring RX/TX ring parameters */
+ struct ethtool_ringparam {
+- u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */
++ __u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */
+
+ /* Read only attributes. These indicate the maximum number
+ * of pending RX/TX ring entries the driver will allow the
+ * user to set.
+ */
+- u32 rx_max_pending;
+- u32 rx_mini_max_pending;
+- u32 rx_jumbo_max_pending;
+- u32 tx_max_pending;
++ __u32 rx_max_pending;
++ __u32 rx_mini_max_pending;
++ __u32 rx_jumbo_max_pending;
++ __u32 tx_max_pending;
+
+ /* Values changeable by the user. The valid values are
+ * in the range 1 to the "*_max_pending" counterpart above.
+ */
+- u32 rx_pending;
+- u32 rx_mini_pending;
+- u32 rx_jumbo_pending;
+- u32 tx_pending;
++ __u32 rx_pending;
++ __u32 rx_mini_pending;
++ __u32 rx_jumbo_pending;
++ __u32 tx_pending;
+ };
+
+ /* for configuring link flow control parameters */
+ struct ethtool_pauseparam {
+- u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */
++ __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */
+
+ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg
+ * being true) the user may set 'autonet' here non-zero to have the
+@@ -210,9 +210,9 @@
+ * then {rx,tx}_pause force the driver to use/not-use pause
+ * flow control.
+ */
+- u32 autoneg;
+- u32 rx_pause;
+- u32 tx_pause;
++ __u32 autoneg;
++ __u32 rx_pause;
++ __u32 tx_pause;
+ };
+
+ #define ETH_GSTRING_LEN 32
+@@ -223,10 +223,10 @@
+
+ /* for passing string sets for data tagging */
+ struct ethtool_gstrings {
+- u32 cmd; /* ETHTOOL_GSTRINGS */
+- u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/
+- u32 len; /* number of strings in the string set */
+- u8 data[0];
++ __u32 cmd; /* ETHTOOL_GSTRINGS */
++ __u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/
++ __u32 len; /* number of strings in the string set */
++ __u8 data[0];
+ };
+
+ enum ethtool_test_flags {
+@@ -236,30 +236,30 @@
+
+ /* for requesting NIC test and getting results*/
+ struct ethtool_test {
+- u32 cmd; /* ETHTOOL_TEST */
+- u32 flags; /* ETH_TEST_FL_xxx */
+- u32 reserved;
+- u32 len; /* result length, in number of u64 elements */
+- u64 data[0];
++ __u32 cmd; /* ETHTOOL_TEST */
++ __u32 flags; /* ETH_TEST_FL_xxx */
++ __u32 reserved;
++ __u32 len; /* result length, in number of __u64 elements */
++ __u64 data[0];
+ };
+
+ /* for dumping NIC-specific statistics */
+ struct ethtool_stats {
+- u32 cmd; /* ETHTOOL_GSTATS */
+- u32 n_stats; /* number of u64's being returned */
+- u64 data[0];
++ __u32 cmd; /* ETHTOOL_GSTATS */
++ __u32 n_stats; /* number of __u64's being returned */
++ __u64 data[0];
+ };
+
+ struct net_device;
+
+ /* Some generic methods drivers may use in their ethtool_ops */
+-u32 ethtool_op_get_link(struct net_device *dev);
+-u32 ethtool_op_get_tx_csum(struct net_device *dev);
+-int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
+-u32 ethtool_op_get_sg(struct net_device *dev);
+-int ethtool_op_set_sg(struct net_device *dev, u32 data);
+-u32 ethtool_op_get_tso(struct net_device *dev);
+-int ethtool_op_set_tso(struct net_device *dev, u32 data);
++__u32 ethtool_op_get_link(struct net_device *dev);
++__u32 ethtool_op_get_tx_csum(struct net_device *dev);
++int ethtool_op_set_tx_csum(struct net_device *dev, __u32 data);
++__u32 ethtool_op_get_sg(struct net_device *dev);
++int ethtool_op_set_sg(struct net_device *dev, __u32 data);
++__u32 ethtool_op_get_tso(struct net_device *dev);
++int ethtool_op_set_tso(struct net_device *dev, __u32 data);
+
+ /**
+ * &ethtool_ops - Alter and report network device settings
+@@ -324,33 +324,33 @@
+ void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);
+ void (*get_wol)(struct net_device *, struct ethtool_wolinfo *);
+ int (*set_wol)(struct net_device *, struct ethtool_wolinfo *);
+- u32 (*get_msglevel)(struct net_device *);
+- void (*set_msglevel)(struct net_device *, u32);
++ __u32 (*get_msglevel)(struct net_device *);
++ void (*set_msglevel)(struct net_device *, __u32);
+ int (*nway_reset)(struct net_device *);
+- u32 (*get_link)(struct net_device *);
++ __u32 (*get_link)(struct net_device *);
+ int (*get_eeprom_len)(struct net_device *);
+- int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
+- int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
++ int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, __u8 *);
++ int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, __u8 *);
+ int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
+ int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
+ void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *);
+ int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *);
+ void (*get_pauseparam)(struct net_device *, struct ethtool_pauseparam*);
+ int (*set_pauseparam)(struct net_device *, struct ethtool_pauseparam*);
+- u32 (*get_rx_csum)(struct net_device *);
+- int (*set_rx_csum)(struct net_device *, u32);
+- u32 (*get_tx_csum)(struct net_device *);
+- int (*set_tx_csum)(struct net_device *, u32);
+- u32 (*get_sg)(struct net_device *);
+- int (*set_sg)(struct net_device *, u32);
+- u32 (*get_tso)(struct net_device *);
+- int (*set_tso)(struct net_device *, u32);
++ __u32 (*get_rx_csum)(struct net_device *);
++ int (*set_rx_csum)(struct net_device *, __u32);
++ __u32 (*get_tx_csum)(struct net_device *);
++ int (*set_tx_csum)(struct net_device *, __u32);
++ __u32 (*get_sg)(struct net_device *);
++ int (*set_sg)(struct net_device *, __u32);
++ __u32 (*get_tso)(struct net_device *);
++ int (*set_tso)(struct net_device *, __u32);
+ int (*self_test_count)(struct net_device *);
+- void (*self_test)(struct net_device *, struct ethtool_test *, u64 *);
+- void (*get_strings)(struct net_device *, u32 stringset, u8 *);
+- int (*phys_id)(struct net_device *, u32);
++ void (*self_test)(struct net_device *, struct ethtool_test *, __u64 *);
++ void (*get_strings)(struct net_device *, __u32 stringset, __u8 *);
++ int (*phys_id)(struct net_device *, __u32);
+ int (*get_stats_count)(struct net_device *);
+- void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
++ void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, __u64 *);
+ int (*begin)(struct net_device *);
+ void (*complete)(struct net_device *);
+ };
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/firmware.h linux-libc-headers-2.6.8.0/include/linux/firmware.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/firmware.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/firmware.h 2004-08-26 05:42:08.000000000 -0500
+@@ -5,7 +5,7 @@
+ #define FIRMWARE_NAME_MAX 30
+ struct firmware {
+ size_t size;
+- u8 *data;
++ __u8 *data;
+ };
+ int request_firmware(const struct firmware **fw, const char *name,
+ struct device *device);
+@@ -15,5 +15,5 @@
+ void (*cont)(const struct firmware *fw, void *context));
+
+ void release_firmware(const struct firmware *fw);
+-void register_firmware(const char *name, const u8 *data, size_t size);
++void register_firmware(const char *name, const __u8 *data, size_t size);
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/fs.h linux-libc-headers-2.6.8.0/include/linux/fs.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/fs.h 2004-08-18 13:16:02.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/fs.h 2004-08-26 05:42:08.000000000 -0500
+@@ -198,7 +198,7 @@
+ /* A jump here: 108-111 have been used for various private purposes. */
+ #define BLKBSZGET _IOR(0x12,112,size_t)
+ #define BLKBSZSET _IOW(0x12,113,size_t)
+-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
++#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (__u64 *arg) */
+
+ #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
+ #define FIBMAP _IO(0x00,1) /* bmap access */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/i2c.h linux-libc-headers-2.6.8.0/include/linux/i2c.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/i2c.h 2004-06-23 16:52:54.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/i2c.h 2004-08-26 05:42:08.000000000 -0500
+@@ -70,36 +70,36 @@
+ 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,
++extern __s32 i2c_smbus_xfer (struct i2c_adapter * adapter, __u16 addr,
+ unsigned short flags,
+- char read_write, u8 command, int size,
++ 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 smbus_access. */
+
+-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
+-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);
+-extern s32 i2c_smbus_process_call(struct i2c_client * client,
+- u8 command, u16 value);
++extern __s32 i2c_smbus_write_quick(struct i2c_client * client, __u8 value);
++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);
++extern __s32 i2c_smbus_process_call(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,
+- u8 *values);
+-extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
+- u8 command, u8 *values);
+-extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
+- u8 command, u8 length,
+- u8 *values);
++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,
++ __u8 *values);
++extern __s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
++ __u8 command, __u8 *values);
++extern __s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
++ __u8 command, __u8 length,
++ __u8 *values);
+
+
+ /*
+@@ -203,9 +203,9 @@
+ using common I2C messages */
+ int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[],
+ int num);
+- int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
++ int (*smbus_xfer) (struct i2c_adapter *adap, __u16 addr,
+ unsigned short flags, char read_write,
+- u8 command, int size, union i2c_smbus_data * data);
++ __u8 command, int size, union i2c_smbus_data * data);
+
+ /* --- these optional/future use for some adapter types.*/
+ int (*slave_send)(struct i2c_adapter *,char*,int);
+@@ -215,7 +215,7 @@
+ int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
+
+ /* To determine what the adapter supports */
+- u32 (*functionality) (struct i2c_adapter *);
++ __u32 (*functionality) (struct i2c_adapter *);
+ };
+
+ /*
+@@ -381,10 +381,10 @@
+
+
+ /* Return the functionality mask */
+-extern u32 i2c_get_functionality (struct i2c_adapter *adap);
++extern __u32 i2c_get_functionality (struct i2c_adapter *adap);
+
+ /* Return 1 if adapter supports everything we need, 0 if not. */
+-extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func);
++extern int i2c_check_functionality (struct i2c_adapter *adap, __u32 func);
+
+ /*
+ * I2C Message - used for pure i2c transaction, also from /dev interface
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/i2o-dev.h linux-libc-headers-2.6.8.0/include/linux/i2o-dev.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/i2o-dev.h 2004-06-23 16:52:54.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/i2o-dev.h 2004-08-26 05:42:08.000000000 -0500
+@@ -29,7 +29,7 @@
+ * I2O Control IOCTLs and structures
+ */
+ #define I2O_MAGIC_NUMBER 'i'
+-#define I2OGETIOPS _IOR(I2O_MAGIC_NUMBER,0,u8[MAX_I2O_CONTROLLERS])
++#define I2OGETIOPS _IOR(I2O_MAGIC_NUMBER,0,__u8[MAX_I2O_CONTROLLERS])
+ #define I2OHRTGET _IOWR(I2O_MAGIC_NUMBER,1,struct i2o_cmd_hrtlct)
+ #define I2OLCTGET _IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
+ #define I2OPARMSET _IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
+@@ -37,7 +37,7 @@
+ #define I2OSWDL _IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
+ #define I2OSWUL _IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
+ #define I2OSWDEL _IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
+-#define I2OVALIDATE _IOR(I2O_MAGIC_NUMBER,8,u32)
++#define I2OVALIDATE _IOR(I2O_MAGIC_NUMBER,8,__u32)
+ #define I2OHTML _IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
+ #define I2OEVTREG _IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
+ #define I2OEVTGET _IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
+@@ -129,65 +129,65 @@
+ #define I2O_BUS_CARDBUS 7
+ #define I2O_BUS_UNKNOWN 0x80
+
+-typedef unsigned char u8;
+-typedef unsigned short u16;
+-typedef unsigned int u32;
++typedef unsigned char __u8;
++typedef unsigned short __u16;
++typedef unsigned int __u32;
+
+ typedef struct _i2o_pci_bus
+ {
+- u8 PciFunctionNumber;
+- u8 PciDeviceNumber;
+- u8 PciBusNumber;
+- u8 reserved;
+- u16 PciVendorID;
+- u16 PciDeviceID;
++ __u8 PciFunctionNumber;
++ __u8 PciDeviceNumber;
++ __u8 PciBusNumber;
++ __u8 reserved;
++ __u16 PciVendorID;
++ __u16 PciDeviceID;
+ } i2o_pci_bus;
+
+ typedef struct _i2o_local_bus
+ {
+- u16 LbBaseIOPort;
+- u16 reserved;
+- u32 LbBaseMemoryAddress;
++ __u16 LbBaseIOPort;
++ __u16 reserved;
++ __u32 LbBaseMemoryAddress;
+ } i2o_local_bus;
+
+ typedef struct _i2o_isa_bus
+ {
+- u16 IsaBaseIOPort;
+- u8 CSN;
+- u8 reserved;
+- u32 IsaBaseMemoryAddress;
++ __u16 IsaBaseIOPort;
++ __u8 CSN;
++ __u8 reserved;
++ __u32 IsaBaseMemoryAddress;
+ } i2o_isa_bus;
+
+ typedef struct _i2o_eisa_bus_info
+ {
+- u16 EisaBaseIOPort;
+- u8 reserved;
+- u8 EisaSlotNumber;
+- u32 EisaBaseMemoryAddress;
++ __u16 EisaBaseIOPort;
++ __u8 reserved;
++ __u8 EisaSlotNumber;
++ __u32 EisaBaseMemoryAddress;
+ } i2o_eisa_bus;
+
+ typedef struct _i2o_mca_bus
+ {
+- u16 McaBaseIOPort;
+- u8 reserved;
+- u8 McaSlotNumber;
+- u32 McaBaseMemoryAddress;
++ __u16 McaBaseIOPort;
++ __u8 reserved;
++ __u8 McaSlotNumber;
++ __u32 McaBaseMemoryAddress;
+ } i2o_mca_bus;
+
+ typedef struct _i2o_other_bus
+ {
+- u16 BaseIOPort;
+- u16 reserved;
+- u32 BaseMemoryAddress;
++ __u16 BaseIOPort;
++ __u16 reserved;
++ __u32 BaseMemoryAddress;
+ } i2o_other_bus;
+
+ typedef struct _i2o_hrt_entry
+ {
+- u32 adapter_id;
+- u32 parent_tid:12;
+- u32 state:4;
+- u32 bus_num:8;
+- u32 bus_type:8;
++ __u32 adapter_id;
++ __u32 parent_tid:12;
++ __u32 state:4;
++ __u32 bus_num:8;
++ __u32 bus_type:8;
+ union
+ {
+ i2o_pci_bus pci_bus;
+@@ -201,69 +201,69 @@
+
+ typedef struct _i2o_hrt
+ {
+- u16 num_entries;
+- u8 entry_len;
+- u8 hrt_version;
+- u32 change_ind;
++ __u16 num_entries;
++ __u8 entry_len;
++ __u8 hrt_version;
++ __u32 change_ind;
+ i2o_hrt_entry hrt_entry[1];
+ } i2o_hrt;
+
+ typedef struct _i2o_lct_entry
+ {
+- u32 entry_size:16;
+- u32 tid:12;
+- u32 reserved:4;
+- u32 change_ind;
+- u32 device_flags;
+- u32 class_id:12;
+- u32 version:4;
+- u32 vendor_id:16;
+- u32 sub_class;
+- u32 user_tid:12;
+- u32 parent_tid:12;
+- u32 bios_info:8;
+- u8 identity_tag[8];
+- u32 event_capabilities;
++ __u32 entry_size:16;
++ __u32 tid:12;
++ __u32 reserved:4;
++ __u32 change_ind;
++ __u32 device_flags;
++ __u32 class_id:12;
++ __u32 version:4;
++ __u32 vendor_id:16;
++ __u32 sub_class;
++ __u32 user_tid:12;
++ __u32 parent_tid:12;
++ __u32 bios_info:8;
++ __u8 identity_tag[8];
++ __u32 event_capabilities;
+ } i2o_lct_entry;
+
+ typedef struct _i2o_lct
+ {
+- u32 table_size:16;
+- u32 boot_tid:12;
+- u32 lct_ver:4;
+- u32 iop_flags;
+- u32 change_ind;
++ __u32 table_size:16;
++ __u32 boot_tid:12;
++ __u32 lct_ver:4;
++ __u32 iop_flags;
++ __u32 change_ind;
+ i2o_lct_entry lct_entry[1];
+ } i2o_lct;
+
+ typedef struct _i2o_status_block
+ {
+- u16 org_id;
+- u16 reserved;
+- u16 iop_id:12;
+- u16 reserved1:4;
+- u16 host_unit_id;
+- u16 segment_number:12;
+- u16 i2o_version:4;
+- u8 iop_state;
+- u8 msg_type;
+- u16 inbound_frame_size;
+- u8 init_code;
+- u8 reserved2;
+- u32 max_inbound_frames;
+- u32 cur_inbound_frames;
+- u32 max_outbound_frames;
++ __u16 org_id;
++ __u16 reserved;
++ __u16 iop_id:12;
++ __u16 reserved1:4;
++ __u16 host_unit_id;
++ __u16 segment_number:12;
++ __u16 i2o_version:4;
++ __u8 iop_state;
++ __u8 msg_type;
++ __u16 inbound_frame_size;
++ __u8 init_code;
++ __u8 reserved2;
++ __u32 max_inbound_frames;
++ __u32 cur_inbound_frames;
++ __u32 max_outbound_frames;
+ char product_id[24];
+- u32 expected_lct_size;
+- u32 iop_capabilities;
+- u32 desired_mem_size;
+- u32 current_mem_size;
+- u32 current_mem_base;
+- u32 desired_io_size;
+- u32 current_io_size;
+- u32 current_io_base;
+- u32 reserved3:24;
+- u32 cmd_status:8;
++ __u32 expected_lct_size;
++ __u32 iop_capabilities;
++ __u32 desired_mem_size;
++ __u32 current_mem_size;
++ __u32 current_mem_base;
++ __u32 desired_io_size;
++ __u32 current_io_size;
++ __u32 current_io_base;
++ __u32 reserved3:24;
++ __u32 cmd_status:8;
+ } i2o_status_block;
+
+ /* Event indicator mask flags */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/isdn/capilli.h linux-libc-headers-2.6.8.0/include/linux/isdn/capilli.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/isdn/capilli.h 2004-03-28 07:52:12.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/isdn/capilli.h 2004-08-26 13:26:47.000000000 -0500
+@@ -43,20 +43,20 @@
+ char *driver_name; /* name of driver */
+ int (*load_firmware)(struct capi_ctr *, capiloaddata *);
+ void (*reset_ctr)(struct capi_ctr *);
+- void (*register_appl)(struct capi_ctr *, u16 appl,
++ void (*register_appl)(struct capi_ctr *, __u16 appl,
+ capi_register_params *);
+- void (*release_appl)(struct capi_ctr *, u16 appl);
+- u16 (*send_message)(struct capi_ctr *, struct sk_buff *skb);
++ void (*release_appl)(struct capi_ctr *, __u16 appl);
++ __u16 (*send_message)(struct capi_ctr *, struct sk_buff *skb);
+
+ char *(*procinfo)(struct capi_ctr *);
+ int (*ctr_read_proc)(char *page, char **start, off_t off,
+ int count, int *eof, struct capi_ctr *card);
+
+ /* filled in before calling ready callback */
+- u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */
++ __u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */
+ capi_version version; /* CAPI_GET_VERSION */
+ capi_profile profile; /* CAPI_GET_PROFILE */
+- u8 serial[CAPI_SERIAL_LEN]; /* CAPI_GET_SERIAL */
++ __u8 serial[CAPI_SERIAL_LEN]; /* CAPI_GET_SERIAL */
+
+ /* management information for kcapi */
+
+@@ -81,7 +81,7 @@
+ void capi_ctr_reseted(struct capi_ctr * card);
+ void capi_ctr_suspend_output(struct capi_ctr * card);
+ void capi_ctr_resume_output(struct capi_ctr * card);
+-void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb);
++void capi_ctr_handle_message(struct capi_ctr * card, __u16 appl, struct sk_buff *skb);
+
+ // ---------------------------------------------------------------------------
+ // needed for AVM capi drivers
+@@ -102,11 +102,11 @@
+ // ---------------------------------------------------------------------------
+ // library functions for use by hardware controller drivers
+
+-void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize);
+-void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci);
+-void capilib_release_appl(struct list_head *head, u16 applid);
++void capilib_new_ncci(struct list_head *head, __u16 applid, __u32 ncci, __u32 winsize);
++void capilib_free_ncci(struct list_head *head, __u16 applid, __u32 ncci);
++void capilib_release_appl(struct list_head *head, __u16 applid);
+ void capilib_release(struct list_head *head);
+-void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
+-u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
++void capilib_data_b3_conf(struct list_head *head, __u16 applid, __u32 ncci, __u16 msgid);
++__u16 capilib_data_b3_req(struct list_head *head, __u16 applid, __u32 ncci, __u16 msgid);
+
+ #endif /* __CAPILLI_H__ */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/jhash.h linux-libc-headers-2.6.8.0/include/linux/jhash.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/jhash.h 2004-03-28 07:52:09.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/jhash.h 2004-08-26 05:42:08.000000000 -0500
+@@ -41,19 +41,19 @@
+ * of bytes. No alignment or length assumptions are made about
+ * the input key.
+ */
+-static inline u32 jhash(const void *key, u32 length, u32 initval)
++static inline __u32 jhash(const void *key, __u32 length, __u32 initval)
+ {
+- u32 a, b, c, len;
+- const u8 *k = key;
++ __u32 a, b, c, len;
++ const __u8 *k = key;
+
+ len = length;
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+
+ while (len >= 12) {
+- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
+- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
+- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
++ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
++ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
++ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
+
+ __jhash_mix(a,b,c);
+
+@@ -63,16 +63,16 @@
+
+ c += length;
+ switch (len) {
+- case 11: c += ((u32)k[10]<<24);
+- case 10: c += ((u32)k[9]<<16);
+- case 9 : c += ((u32)k[8]<<8);
+- case 8 : b += ((u32)k[7]<<24);
+- case 7 : b += ((u32)k[6]<<16);
+- case 6 : b += ((u32)k[5]<<8);
++ case 11: c += ((__u32)k[10]<<24);
++ case 10: c += ((__u32)k[9]<<16);
++ case 9 : c += ((__u32)k[8]<<8);
++ case 8 : b += ((__u32)k[7]<<24);
++ case 7 : b += ((__u32)k[6]<<16);
++ case 6 : b += ((__u32)k[5]<<8);
+ case 5 : b += k[4];
+- case 4 : a += ((u32)k[3]<<24);
+- case 3 : a += ((u32)k[2]<<16);
+- case 2 : a += ((u32)k[1]<<8);
++ case 4 : a += ((__u32)k[3]<<24);
++ case 3 : a += ((__u32)k[2]<<16);
++ case 2 : a += ((__u32)k[1]<<8);
+ case 1 : a += k[0];
+ };
+
+@@ -81,12 +81,12 @@
+ return c;
+ }
+
+-/* A special optimized version that handles 1 or more of u32s.
+- * The length parameter here is the number of u32s in the key.
++/* A special optimized version that handles 1 or more of __u32s.
++ * The length parameter here is the number of __u32s in the key.
+ */
+-static inline u32 jhash2(u32 *k, u32 length, u32 initval)
++static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
+ {
+- u32 a, b, c, len;
++ __u32 a, b, c, len;
+
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+@@ -119,7 +119,7 @@
+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
+ * done at the end is not done here.
+ */
+-static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
++static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
+ {
+ a += JHASH_GOLDEN_RATIO;
+ b += JHASH_GOLDEN_RATIO;
+@@ -130,12 +130,12 @@
+ return c;
+ }
+
+-static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
++static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
+ {
+ return jhash_3words(a, b, 0, initval);
+ }
+
+-static inline u32 jhash_1word(u32 a, u32 initval)
++static inline __u32 jhash_1word(__u32 a, __u32 initval)
+ {
+ return jhash_3words(a, 0, 0, initval);
+ }
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/jiffies.h linux-libc-headers-2.6.8.0/include/linux/jiffies.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/jiffies.h 2004-01-17 17:04:30.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/jiffies.h 2004-08-26 13:26:33.000000000 -0500
+@@ -12,15 +12,15 @@
+ * without sampling the sequence number in xtime_lock.
+ * get_jiffies_64() will do this for you as appropriate.
+ */
+-extern u64 jiffies_64;
++extern __u64 jiffies_64;
+ extern unsigned long volatile jiffies;
+
+ #if (BITS_PER_LONG < 64)
+-u64 get_jiffies_64(void);
++__u64 get_jiffies_64(void);
+ #else
+-static inline u64 get_jiffies_64(void)
++static inline __u64 get_jiffies_64(void)
+ {
+- return (u64)jiffies;
++ return (__u64)jiffies;
+ }
+ #endif
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/kernel_stat.h linux-libc-headers-2.6.8.0/include/linux/kernel_stat.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/kernel_stat.h 2004-04-19 16:13:51.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/kernel_stat.h 2004-08-26 05:42:08.000000000 -0500
+@@ -12,13 +12,13 @@
+ */
+
+ struct cpu_usage_stat {
+- u64 user;
+- u64 nice;
+- u64 system;
+- u64 softirq;
+- u64 irq;
+- u64 idle;
+- u64 iowait;
++ __u64 user;
++ __u64 nice;
++ __u64 system;
++ __u64 softirq;
++ __u64 irq;
++ __u64 idle;
++ __u64 iowait;
+ };
+
+ struct kernel_stat {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/libata.h linux-libc-headers-2.6.8.0/include/linux/libata.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/libata.h 2004-08-18 13:16:03.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/libata.h 2004-08-26 05:42:08.000000000 -0500
+@@ -160,7 +160,7 @@
+ struct ata_queued_cmd;
+
+ /* typedefs */
+-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
++typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, __u8 drv_stat);
+
+ struct ata_ioports {
+ unsigned long cmd_addr;
+@@ -246,18 +246,18 @@
+ };
+
+ struct ata_device {
+- u64 n_sectors; /* size of device, if ATA */
++ __u64 n_sectors; /* size of device, if ATA */
+ unsigned long flags; /* ATA_DFLAG_xxx */
+ unsigned int class; /* ATA_DEV_xxx */
+ unsigned int devno; /* 0 or 1 */
+- u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
++ __u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+ unsigned int pio_mode;
+ unsigned int udma_mode;
+
+ /* cache info about current transfer mode */
+- u8 xfer_protocol; /* taskfile xfer protocol */
+- u8 read_cmd; /* opcode to use on read */
+- u8 write_cmd; /* opcode to use on write */
++ __u8 xfer_protocol; /* taskfile xfer protocol */
++ __u8 read_cmd; /* opcode to use on read */
++ __u8 write_cmd; /* opcode to use on write */
+ };
+
+ struct ata_port {
+@@ -272,8 +272,8 @@
+
+ struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
+
+- u8 ctl; /* cache of ATA control register */
+- u8 last_ctl; /* Cache last written value */
++ __u8 ctl; /* cache of ATA control register */
++ __u8 last_ctl; /* Cache last written value */
+ unsigned int bus_state;
+ unsigned int port_state;
+ unsigned int pio_mask;
+@@ -312,7 +312,7 @@
+ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
+
+ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
+- u8 (*check_status)(struct ata_port *ap);
++ __u8 (*check_status)(struct ata_port *ap);
+
+ void (*phy_reset) (struct ata_port *ap);
+ void (*post_set_mode) (struct ata_port *ap);
+@@ -328,9 +328,9 @@
+ irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+ void (*irq_clear) (struct ata_port *);
+
+- u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
++ __u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
+ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
+- u32 val);
++ __u32 val);
+
+ int (*port_start) (struct ata_port *ap);
+ void (*port_stop) (struct ata_port *ap);
+@@ -374,10 +374,10 @@
+ extern void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+ extern void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf);
+ extern void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+-extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
+-extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
+-extern u8 ata_check_status_pio(struct ata_port *ap);
+-extern u8 ata_check_status_mmio(struct ata_port *ap);
++extern void ata_tf_to_fis(struct ata_taskfile *tf, __u8 *fis, __u8 pmp);
++extern void ata_tf_from_fis(__u8 *fis, struct ata_taskfile *tf);
++extern __u8 ata_check_status_pio(struct ata_port *ap);
++extern __u8 ata_check_status_mmio(struct ata_port *ap);
+ extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
+ extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+ extern int ata_port_start (struct ata_port *ap);
+@@ -397,7 +397,7 @@
+ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+ extern void ata_bmdma_irq_clear(struct ata_port *ap);
+ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
+-extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
++extern void ata_qc_complete(struct ata_queued_cmd *qc, __u8 drv_stat);
+ extern void ata_eng_timeout(struct ata_port *ap);
+ extern int ata_std_bios_param(struct scsi_device *sdev,
+ struct block_device *bdev,
+@@ -416,7 +416,7 @@
+ (dev->class == ATA_DEV_ATAPI));
+ }
+
+-static inline u8 ata_chk_err(struct ata_port *ap)
++static inline __u8 ata_chk_err(struct ata_port *ap)
+ {
+ if (ap->flags & ATA_FLAG_MMIO) {
+ return readb((void *) ap->ioaddr.error_addr);
+@@ -424,12 +424,12 @@
+ return inb(ap->ioaddr.error_addr);
+ }
+
+-static inline u8 ata_chk_status(struct ata_port *ap)
++static inline __u8 ata_chk_status(struct ata_port *ap)
+ {
+ return ap->ops->check_status(ap);
+ }
+
+-static inline u8 ata_altstatus(struct ata_port *ap)
++static inline __u8 ata_altstatus(struct ata_port *ap)
+ {
+ if (ap->flags & ATA_FLAG_MMIO)
+ return readb(ap->ioaddr.altstatus_addr);
+@@ -442,10 +442,10 @@
+ ndelay(400);
+ }
+
+-static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
++static inline __u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
+ unsigned int max)
+ {
+- u8 status;
++ __u8 status;
+
+ do {
+ udelay(10);
+@@ -456,9 +456,9 @@
+ return status;
+ }
+
+-static inline u8 ata_wait_idle(struct ata_port *ap)
++static inline __u8 ata_wait_idle(struct ata_port *ap)
+ {
+- u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++ __u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+ if (status & (ATA_BUSY | ATA_DRQ)) {
+ unsigned long l = ap->ioaddr.status_addr;
+@@ -495,10 +495,10 @@
+ tf->device = ATA_DEVICE_OBS | ATA_DEV1;
+ }
+
+-static inline u8 ata_irq_on(struct ata_port *ap)
++static inline __u8 ata_irq_on(struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+- u8 tmp;
++ __u8 tmp;
+
+ ap->ctl &= ~ATA_NIEN;
+ ap->last_ctl = ap->ctl;
+@@ -514,10 +514,10 @@
+ return tmp;
+ }
+
+-static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
++static inline __u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
+ {
+ unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
+- u8 host_stat, post_stat, status;
++ __u8 host_stat, post_stat, status;
+
+ status = ata_busy_wait(ap, bits, 1000);
+ if (status & bits)
+@@ -545,12 +545,12 @@
+ return status;
+ }
+
+-static inline u32 scr_read(struct ata_port *ap, unsigned int reg)
++static inline __u32 scr_read(struct ata_port *ap, unsigned int reg)
+ {
+ return ap->ops->scr_read(ap, reg);
+ }
+
+-static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
++static inline void scr_write(struct ata_port *ap, unsigned int reg, __u32 val)
+ {
+ ap->ops->scr_write(ap, reg, val);
+ }
+@@ -589,9 +589,9 @@
+ }
+ }
+
+-static inline u8 ata_bmdma_status(struct ata_port *ap)
++static inline __u8 ata_bmdma_status(struct ata_port *ap)
+ {
+- u8 host_stat;
++ __u8 host_stat;
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void *mmio = (void *) ap->ioaddr.bmdma_addr;
+ host_stat = readb(mmio + ATA_DMA_STATUS);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/bind.h linux-libc-headers-2.6.8.0/include/linux/lockd/bind.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/bind.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/bind.h 2004-08-26 05:42:08.000000000 -0500
+@@ -18,7 +18,7 @@
+ * This is the set of functions for lockd->nfsd communication
+ */
+ struct nlmsvc_binding {
+- u32 (*fopen)(struct svc_rqst *,
++ __u32 (*fopen)(struct svc_rqst *,
+ struct nfs_fh *,
+ struct file *);
+ void (*fclose)(struct file *);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/nlm.h linux-libc-headers-2.6.8.0/include/linux/lockd/nlm.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/nlm.h 2004-01-17 17:04:34.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/nlm.h 2004-08-26 05:42:08.000000000 -0500
+@@ -11,8 +11,8 @@
+
+
+ /* Maximum file offset in file_lock.fl_end */
+-# define NLM_OFFSET_MAX ((s32) 0x7fffffff)
+-# define NLM4_OFFSET_MAX ((s64) ((~(u64)0) >> 1))
++# define NLM_OFFSET_MAX ((__s32) 0x7fffffff)
++# define NLM4_OFFSET_MAX ((__s64) ((~(__u64)0) >> 1))
+
+ /* Return states for NLM */
+ enum {
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/share.h linux-libc-headers-2.6.8.0/include/linux/lockd/share.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/share.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/share.h 2004-08-26 13:26:43.000000000 -0500
+@@ -17,13 +17,13 @@
+ struct nlm_host * s_host; /* client host */
+ struct nlm_file * s_file; /* shared file */
+ struct xdr_netobj s_owner; /* owner handle */
+- u32 s_access; /* access mode */
+- u32 s_mode; /* deny mode */
++ __u32 s_access; /* access mode */
++ __u32 s_mode; /* deny mode */
+ };
+
+-u32 nlmsvc_share_file(struct nlm_host *, struct nlm_file *,
++__u32 nlmsvc_share_file(struct nlm_host *, struct nlm_file *,
+ struct nlm_args *);
+-u32 nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *,
++__u32 nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *,
+ struct nlm_args *);
+ int nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *, int);
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/sm_inter.h linux-libc-headers-2.6.8.0/include/linux/lockd/sm_inter.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/sm_inter.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/sm_inter.h 2004-08-26 05:42:08.000000000 -0500
+@@ -24,23 +24,23 @@
+ * Arguments for all calls to statd
+ */
+ struct nsm_args {
+- u32 addr; /* remote address */
+- u32 prog; /* RPC callback info */
+- u32 vers;
+- u32 proc;
+- u32 proto; /* protocol (udp/tcp) plus server/client flag */
++ __u32 addr; /* remote address */
++ __u32 prog; /* RPC callback info */
++ __u32 vers;
++ __u32 proc;
++ __u32 proto; /* protocol (udp/tcp) plus server/client flag */
+ };
+
+ /*
+ * Result returned by statd
+ */
+ struct nsm_res {
+- u32 status;
+- u32 state;
++ __u32 status;
++ __u32 state;
+ };
+
+ int nsm_monitor(struct nlm_host *);
+ int nsm_unmonitor(struct nlm_host *);
+-extern u32 nsm_local_state;
++extern __u32 nsm_local_state;
+
+ #endif /* LINUX_LOCKD_SM_INTER_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/xdr.h linux-libc-headers-2.6.8.0/include/linux/lockd/xdr.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/xdr.h 2004-01-05 12:42:33.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/xdr.h 2004-08-26 05:42:08.000000000 -0500
+@@ -48,12 +48,12 @@
+ struct nlm_args {
+ struct nlm_cookie cookie;
+ struct nlm_lock lock;
+- u32 block;
+- u32 reclaim;
+- u32 state;
+- u32 monitor;
+- u32 fsm_access;
+- u32 fsm_mode;
++ __u32 block;
++ __u32 reclaim;
++ __u32 state;
++ __u32 monitor;
++ __u32 fsm_access;
++ __u32 fsm_mode;
+ };
+
+ typedef struct nlm_args nlm_args;
+@@ -63,7 +63,7 @@
+ */
+ struct nlm_res {
+ struct nlm_cookie cookie;
+- u32 status;
++ __u32 status;
+ struct nlm_lock lock;
+ };
+
+@@ -73,10 +73,10 @@
+ struct nlm_reboot {
+ char * mon;
+ int len;
+- u32 state;
+- u32 addr;
+- u32 vers;
+- u32 proto;
++ __u32 state;
++ __u32 addr;
++ __u32 vers;
++ __u32 proto;
+ };
+
+ /*
+@@ -84,24 +84,24 @@
+ */
+ #define NLMSVC_XDRSIZE sizeof(struct nlm_args)
+
+-int nlmsvc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlmsvc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlmsvc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlmsvc_encode_void(struct svc_rqst *, u32 *, void *);
+-int nlmsvc_decode_void(struct svc_rqst *, u32 *, void *);
+-int nlmsvc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlmsvc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlmsvc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *);
++int nlmsvc_decode_testargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_encode_testres(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlmsvc_decode_lockargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_decode_cancargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_decode_unlockargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_encode_res(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlmsvc_decode_res(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlmsvc_encode_void(struct svc_rqst *, __u32 *, void *);
++int nlmsvc_decode_void(struct svc_rqst *, __u32 *, void *);
++int nlmsvc_decode_shareargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_encode_shareres(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlmsvc_decode_notify(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlmsvc_decode_reboot(struct svc_rqst *, __u32 *, struct nlm_reboot *);
+ /*
+-int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
++int nlmclt_encode_testargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_lockargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_cancargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_unlockargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
+ */
+
+ #endif /* LOCKD_XDR_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/lockd/xdr4.h linux-libc-headers-2.6.8.0/include/linux/lockd/xdr4.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/lockd/xdr4.h 2004-01-05 12:42:33.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/lockd/xdr4.h 2004-08-26 05:42:08.000000000 -0500
+@@ -22,24 +22,24 @@
+
+
+
+-int nlm4svc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlm4svc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlm4svc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlm4svc_encode_void(struct svc_rqst *, u32 *, void *);
+-int nlm4svc_decode_void(struct svc_rqst *, u32 *, void *);
+-int nlm4svc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *);
+-int nlm4svc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *);
+-int nlm4svc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *);
++int nlm4svc_decode_testargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_encode_testres(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlm4svc_decode_lockargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_decode_cancargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_decode_unlockargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_encode_res(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlm4svc_decode_res(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlm4svc_encode_void(struct svc_rqst *, __u32 *, void *);
++int nlm4svc_decode_void(struct svc_rqst *, __u32 *, void *);
++int nlm4svc_decode_shareargs(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_encode_shareres(struct svc_rqst *, __u32 *, struct nlm_res *);
++int nlm4svc_decode_notify(struct svc_rqst *, __u32 *, struct nlm_args *);
++int nlm4svc_decode_reboot(struct svc_rqst *, __u32 *, struct nlm_reboot *);
+ /*
+-int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
+-int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
++int nlmclt_encode_testargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_lockargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_cancargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
++int nlmclt_encode_unlockargs(struct rpc_rqst *, __u32 *, struct nlm_args *);
+ */
+
+ #endif /* LOCKD_XDR4_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/mca.h linux-libc-headers-2.6.8.0/include/linux/mca.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/mca.h 2004-08-18 13:16:03.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/mca.h 2004-08-26 05:42:08.000000000 -0500
+@@ -50,7 +50,7 @@
+ };
+
+ struct mca_device {
+- u64 dma_mask;
++ __u64 dma_mask;
+ int pos_id;
+ int slot;
+
+@@ -91,7 +91,7 @@
+ };
+
+ struct mca_bus {
+- u64 default_dma_mask;
++ __u64 default_dma_mask;
+ int number;
+ struct mca_bus_accessor_functions f;
+ struct device dev;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/mii.h linux-libc-headers-2.6.8.0/include/linux/mii.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/mii.h 2004-06-23 16:52:55.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/mii.h 2004-08-26 05:42:08.000000000 -0500
+@@ -138,10 +138,10 @@
+
+ /* This structure is used in all SIOCxMIIxxx ioctl calls */
+ struct mii_ioctl_data {
+- u16 phy_id;
+- u16 reg_num;
+- u16 val_in;
+- u16 val_out;
++ __u16 phy_id;
++ __u16 reg_num;
++ __u16 val_in;
++ __u16 val_out;
+ };
+
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/mtd/map.h linux-libc-headers-2.6.8.0/include/linux/mtd/map.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/mtd/map.h 2004-08-18 13:16:06.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/mtd/map.h 2004-08-26 05:42:08.000000000 -0500
+@@ -36,20 +36,20 @@
+ int buswidth; /* in octets */
+
+ #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
+- u8 (*read8)(struct map_info *, unsigned long);
+- u16 (*read16)(struct map_info *, unsigned long);
+- u32 (*read32)(struct map_info *, unsigned long);
+- u64 (*read64)(struct map_info *, unsigned long);
++ __u8 (*read8)(struct map_info *, unsigned long);
++ __u16 (*read16)(struct map_info *, unsigned long);
++ __u32 (*read32)(struct map_info *, unsigned long);
++ __u64 (*read64)(struct map_info *, unsigned long);
+ /* If it returned a 'long' I'd call it readl.
+ * It doesn't.
+ * I won't.
+ * dwmw2 */
+
+ void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
+- void (*write8)(struct map_info *, u8, unsigned long);
+- void (*write16)(struct map_info *, u16, unsigned long);
+- void (*write32)(struct map_info *, u32, unsigned long);
+- void (*write64)(struct map_info *, u64, unsigned long);
++ void (*write8)(struct map_info *, __u8, unsigned long);
++ void (*write16)(struct map_info *, __u16, unsigned long);
++ void (*write32)(struct map_info *, __u32, unsigned long);
++ void (*write64)(struct map_info *, __u64, unsigned long);
+ void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
+
+ /* We can perhaps put in 'point' and 'unpoint' methods, if we really
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/mtd/nand.h linux-libc-headers-2.6.8.0/include/linux/mtd/nand.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/mtd/nand.h 2004-08-18 13:16:06.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/mtd/nand.h 2004-08-26 05:42:08.000000000 -0500
+@@ -271,8 +271,8 @@
+
+ u_char (*read_byte)(struct mtd_info *mtd);
+ void (*write_byte)(struct mtd_info *mtd, u_char byte);
+- u16 (*read_word)(struct mtd_info *mtd);
+- void (*write_word)(struct mtd_info *mtd, u16 word);
++ __u16 (*read_word)(struct mtd_info *mtd);
++ void (*write_word)(struct mtd_info *mtd, __u16 word);
+
+ void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+ void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/mtd/pmc551.h linux-libc-headers-2.6.8.0/include/linux/mtd/pmc551.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/mtd/pmc551.h 2004-03-28 07:52:13.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/mtd/pmc551.h 2004-08-26 05:42:08.000000000 -0500
+@@ -25,9 +25,9 @@
+ struct mypriv {
+ struct pci_dev *dev;
+ u_char *start;
+- u32 base_map0;
+- u32 curr_map0;
+- u32 asize;
++ __u32 base_map0;
++ __u32 curr_map0;
++ __u32 asize;
+ struct mtd_info *nextpmc551;
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nbd.h linux-libc-headers-2.6.8.0/include/linux/nbd.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nbd.h 2004-03-28 07:52:09.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/nbd.h 2004-08-26 05:42:08.000000000 -0500
+@@ -45,11 +45,11 @@
+ * server. All data are in network byte order.
+ */
+ struct nbd_request {
+- u32 magic;
+- u32 type; /* == READ || == WRITE */
++ __u32 magic;
++ __u32 type; /* == READ || == WRITE */
+ char handle[8];
+- u64 from;
+- u32 len;
++ __u64 from;
++ __u32 len;
+ }
+ #ifdef __GNUC__
+ __attribute__ ((packed))
+@@ -61,8 +61,8 @@
+ * it has completed an I/O request (or an error occurs).
+ */
+ struct nbd_reply {
+- u32 magic;
+- u32 error; /* 0 = ok, else error */
++ __u32 magic;
++ __u32 error; /* 0 = ok, else error */
+ char handle[8]; /* handle you got from request */
+ };
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfs_fs_i.h linux-libc-headers-2.6.8.0/include/linux/nfs_fs_i.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfs_fs_i.h 2004-01-17 17:04:31.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/nfs_fs_i.h 2004-08-26 05:42:08.000000000 -0500
+@@ -8,8 +8,8 @@
+ * NFS lock info
+ */
+ struct nfs_lock_info {
+- u32 state;
+- u32 flags;
++ __u32 state;
++ __u32 flags;
+ struct nlm_host *host;
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfs_fs_sb.h linux-libc-headers-2.6.8.0/include/linux/nfs_fs_sb.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfs_fs_sb.h 2004-06-09 07:00:50.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfs_fs_sb.h 2004-08-26 05:42:08.000000000 -0500
+@@ -37,10 +37,10 @@
+ struct list_head nfs4_siblings; /* List of other nfs_server structs
+ * that share the same clientid
+ */
+- u32 attr_bitmask[2];/* V4 bitmask representing the set
++ __u32 attr_bitmask[2];/* V4 bitmask representing the set
+ of attributes supported on this
+ filesystem */
+- u32 acl_bitmask; /* V4 bitmask representing the ACEs
++ __u32 acl_bitmask; /* V4 bitmask representing the ACEs
+ that are supported on this
+ filesystem */
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfs_xdr.h linux-libc-headers-2.6.8.0/include/linux/nfs_xdr.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfs_xdr.h 2004-06-09 07:00:50.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfs_xdr.h 2004-08-26 05:42:08.000000000 -0500
+@@ -90,9 +90,9 @@
+ };
+
+ struct nfs4_change_info {
+- u32 atomic;
+- u64 before;
+- u64 after;
++ __u32 atomic;
++ __u64 before;
++ __u64 after;
+ };
+
+ /*
+@@ -112,7 +112,7 @@
+ } u;
+ const struct qstr * name;
+ const struct nfs_server *server; /* Needed for ID mapping */
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs_openres {
+@@ -168,7 +168,7 @@
+ * */
+ struct nfs_lowner {
+ __u64 clientid;
+- u32 id;
++ __u32 id;
+ };
+
+ struct nfs_open_to_lock {
+@@ -328,7 +328,7 @@
+ nfs4_stateid stateid;
+ struct iattr * iap;
+ const struct nfs_server * server; /* Needed for name mapping */
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs_setattrres {
+@@ -482,32 +482,32 @@
+
+ #ifdef CONFIG_NFS_V4
+
+-typedef u64 clientid4;
++typedef __u64 clientid4;
+
+ struct nfs4_accessargs {
+ const struct nfs_fh * fh;
+- u32 access;
++ __u32 access;
+ };
+
+ struct nfs4_accessres {
+- u32 supported;
+- u32 access;
++ __u32 supported;
++ __u32 access;
+ };
+
+ struct nfs4_create_arg {
+- u32 ftype;
++ __u32 ftype;
+ union {
+ struct qstr * symlink; /* NF4LNK */
+ struct {
+- u32 specdata1;
+- u32 specdata2;
++ __u32 specdata1;
++ __u32 specdata2;
+ } device; /* NF4BLK, NF4CHR */
+ } u;
+ const struct qstr * name;
+ const struct nfs_server * server;
+ const struct iattr * attrs;
+ const struct nfs_fh * dir_fh;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_create_res {
+@@ -519,12 +519,12 @@
+
+ struct nfs4_fsinfo_arg {
+ const struct nfs_fh * fh;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_getattr_arg {
+ const struct nfs_fh * fh;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_getattr_res {
+@@ -541,7 +541,7 @@
+ struct nfs4_lookup_arg {
+ const struct nfs_fh * dir_fh;
+ const struct qstr * name;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_lookup_res {
+@@ -551,19 +551,19 @@
+ };
+
+ struct nfs4_lookup_root_arg {
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_pathconf_arg {
+ const struct nfs_fh * fh;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_readdir_arg {
+ const struct nfs_fh * fh;
+- u64 cookie;
++ __u64 cookie;
+ nfs4_verifier verifier;
+- u32 count;
++ __u32 count;
+ struct page ** pages; /* zero-copy data */
+ unsigned int pgbase; /* zero-copy data */
+ };
+@@ -575,7 +575,7 @@
+
+ struct nfs4_readlink {
+ const struct nfs_fh * fh;
+- u32 count; /* zero-copy data */
++ __u32 count; /* zero-copy data */
+ struct page ** pages; /* zero-copy data */
+ };
+
+@@ -599,23 +599,23 @@
+ struct nfs4_setclientid {
+ nfs4_verifier sc_verifier; /* request */
+ char * sc_name; /* request */
+- u32 sc_prog; /* request */
++ __u32 sc_prog; /* request */
+ char sc_netid[4]; /* request */
+ char sc_uaddr[24]; /* request */
+- u32 sc_cb_ident; /* request */
++ __u32 sc_cb_ident; /* request */
+ struct nfs4_client * sc_state; /* response */
+ };
+
+ struct nfs4_statfs_arg {
+ const struct nfs_fh * fh;
+- const u32 * bitmask;
++ const __u32 * bitmask;
+ };
+
+ struct nfs4_server_caps_res {
+- u32 attr_bitmask[2];
+- u32 acl_bitmask;
+- u32 has_links;
+- u32 has_symlinks;
++ __u32 attr_bitmask[2];
++ __u32 acl_bitmask;
++ __u32 has_links;
++ __u32 has_symlinks;
+ };
+
+ #endif /* CONFIG_NFS_V4 */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/state.h linux-libc-headers-2.6.8.0/include/linux/nfsd/state.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/state.h 2004-08-18 13:16:07.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfsd/state.h 2004-08-26 05:42:08.000000000 -0500
+@@ -41,18 +41,18 @@
+
+ #define NFS4_OPAQUE_LIMIT 1024
+ typedef struct {
+- u32 cl_boot;
+- u32 cl_id;
++ __u32 cl_boot;
++ __u32 cl_id;
+ } clientid_t;
+
+ typedef struct {
+- u32 so_boot;
+- u32 so_stateownerid;
+- u32 so_fileid;
++ __u32 so_boot;
++ __u32 so_stateownerid;
++ __u32 so_fileid;
+ } stateid_opaque_t;
+
+ typedef struct {
+- u32 si_generation;
++ __u32 si_generation;
+ stateid_opaque_t si_opaque;
+ } stateid_t;
+ #define si_boot si_opaque.so_boot
+@@ -68,14 +68,14 @@
+ /* client delegation callback info */
+ struct nfs4_callback {
+ /* SETCLIENTID info */
+- u32 cb_parsed; /* addr parsed */
+- u32 cb_addr;
++ __u32 cb_parsed; /* addr parsed */
++ __u32 cb_addr;
+ unsigned short cb_port;
+- u32 cb_prog;
+- u32 cb_ident;
++ __u32 cb_prog;
++ __u32 cb_ident;
+ struct xdr_netobj cb_netid;
+ /* RPC client info */
+- u32 cb_set; /* successful CB_NULL call */
++ __u32 cb_set; /* successful CB_NULL call */
+ struct rpc_program cb_program;
+ struct rpc_stat cb_stat;
+ struct rpc_clnt * cb_client;
+@@ -99,7 +99,7 @@
+ struct xdr_netobj cl_name; /* id generated by client */
+ nfs4_verifier cl_verifier; /* generated by client */
+ time_t cl_time; /* time of last lease renewal */
+- u32 cl_addr; /* client ipaddress */
++ __u32 cl_addr; /* client ipaddress */
+ struct svc_cred cl_cred; /* setclientid principal */
+ clientid_t cl_clientid; /* generated by server */
+ nfs4_verifier cl_confirm; /* generated by server */
+@@ -116,7 +116,7 @@
+ struct list_head cr_strhash; /* hash by cr_name */
+ struct xdr_netobj cr_name; /* id generated by client */
+ time_t cr_first_state; /* first state aquisition */
+- u32 cr_expired; /* boolean: lease expired? */
++ __u32 cr_expired; /* boolean: lease expired? */
+ };
+
+ static inline void
+@@ -139,7 +139,7 @@
+ * is cached.
+ */
+ struct nfs4_replay {
+- u32 rp_status;
++ __u32 rp_status;
+ unsigned int rp_buflen;
+ char *rp_buf;
+ unsigned intrp_allocated;
+@@ -175,9 +175,9 @@
+ struct list_head so_close_lru; /* tail queue */
+ time_t so_time; /* time of placement on so_close_lru */
+ int so_is_open_owner; /* 1=openowner,0=lockowner */
+- u32 so_id;
++ __u32 so_id;
+ struct nfs4_client * so_client;
+- u32 so_seqid;
++ __u32 so_seqid;
+ struct xdr_netobj so_owner; /* open owner name */
+ int so_confirmed; /* successful OPEN_CONFIRM? */
+ struct nfs4_replay so_replay;
+@@ -192,7 +192,7 @@
+ struct list_head fi_hash; /* hash by "struct inode *" */
+ struct list_head fi_perfile; /* list: nfs4_stateid */
+ struct inode *fi_inode;
+- u32 fi_id; /* used with stateowner->so_id
++ __u32 fi_id; /* used with stateowner->so_id
+ * for stateid_hashtbl hash */
+ };
+
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr.h linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr.h 2004-08-18 13:16:07.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr.h 2004-08-26 05:42:08.000000000 -0500
+@@ -83,7 +83,7 @@
+ struct svc_fh fh;
+ __u32 cookie;
+ __u32 count;
+- u32 * buffer;
++ __u32 * buffer;
+ };
+
+ struct nfsd_attrstat {
+@@ -107,9 +107,9 @@
+ int count;
+
+ struct readdir_cd common;
+- u32 * buffer;
++ __u32 * buffer;
+ int buflen;
+- u32 * offset;
++ __u32 * offset;
+ };
+
+ struct nfsd_statfsres {
+@@ -134,39 +134,39 @@
+ #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore)
+
+
+-int nfssvc_decode_void(struct svc_rqst *, u32 *, void *);
+-int nfssvc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
+-int nfssvc_decode_sattrargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_void(struct svc_rqst *, __u32 *, void *);
++int nfssvc_decode_fhandle(struct svc_rqst *, __u32 *, struct nfsd_fhandle *);
++int nfssvc_decode_sattrargs(struct svc_rqst *, __u32 *,
+ struct nfsd_sattrargs *);
+-int nfssvc_decode_diropargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_diropargs(struct svc_rqst *, __u32 *,
+ struct nfsd_diropargs *);
+-int nfssvc_decode_readargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_readargs(struct svc_rqst *, __u32 *,
+ struct nfsd_readargs *);
+-int nfssvc_decode_writeargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_writeargs(struct svc_rqst *, __u32 *,
+ struct nfsd_writeargs *);
+-int nfssvc_decode_createargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_createargs(struct svc_rqst *, __u32 *,
+ struct nfsd_createargs *);
+-int nfssvc_decode_renameargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_renameargs(struct svc_rqst *, __u32 *,
+ struct nfsd_renameargs *);
+-int nfssvc_decode_readlinkargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_readlinkargs(struct svc_rqst *, __u32 *,
+ struct nfsd_readlinkargs *);
+-int nfssvc_decode_linkargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_linkargs(struct svc_rqst *, __u32 *,
+ struct nfsd_linkargs *);
+-int nfssvc_decode_symlinkargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_symlinkargs(struct svc_rqst *, __u32 *,
+ struct nfsd_symlinkargs *);
+-int nfssvc_decode_readdirargs(struct svc_rqst *, u32 *,
++int nfssvc_decode_readdirargs(struct svc_rqst *, __u32 *,
+ struct nfsd_readdirargs *);
+-int nfssvc_encode_void(struct svc_rqst *, u32 *, void *);
+-int nfssvc_encode_attrstat(struct svc_rqst *, u32 *, struct nfsd_attrstat *);
+-int nfssvc_encode_diropres(struct svc_rqst *, u32 *, struct nfsd_diropres *);
+-int nfssvc_encode_readlinkres(struct svc_rqst *, u32 *, struct nfsd_readlinkres *);
+-int nfssvc_encode_readres(struct svc_rqst *, u32 *, struct nfsd_readres *);
+-int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *);
+-int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *);
++int nfssvc_encode_void(struct svc_rqst *, __u32 *, void *);
++int nfssvc_encode_attrstat(struct svc_rqst *, __u32 *, struct nfsd_attrstat *);
++int nfssvc_encode_diropres(struct svc_rqst *, __u32 *, struct nfsd_diropres *);
++int nfssvc_encode_readlinkres(struct svc_rqst *, __u32 *, struct nfsd_readlinkres *);
++int nfssvc_encode_readres(struct svc_rqst *, __u32 *, struct nfsd_readres *);
++int nfssvc_encode_statfsres(struct svc_rqst *, __u32 *, struct nfsd_statfsres *);
++int nfssvc_encode_readdirres(struct svc_rqst *, __u32 *, struct nfsd_readdirres *);
+
+ int nfssvc_encode_entry(struct readdir_cd *, const char *name,
+ int namlen, loff_t offset, ino_t ino, unsigned int);
+
+-int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
++int nfssvc_release_fhandle(struct svc_rqst *, __u32 *, struct nfsd_fhandle *);
+
+ #endif /* LINUX_NFSD_H */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr3.h linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr3.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr3.h 2004-08-18 13:16:07.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr3.h 2004-08-26 05:42:08.000000000 -0500
+@@ -101,7 +101,7 @@
+ __u32 dircount;
+ __u32 count;
+ __u32 * verf;
+- u32 * buffer;
++ __u32 * buffer;
+ };
+
+ struct nfsd3_commitargs {
+@@ -167,10 +167,10 @@
+ __u32 verf[2];
+
+ struct readdir_cd common;
+- u32 * buffer;
++ __u32 * buffer;
+ int buflen;
+- u32 * offset;
+- u32 * offset1;
++ __u32 * offset;
++ __u32 * offset1;
+ struct svc_rqst * rqstp;
+
+ };
+@@ -245,70 +245,70 @@
+
+ #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
+
+-int nfs3svc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
+-int nfs3svc_decode_sattrargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_fhandle(struct svc_rqst *, __u32 *, struct nfsd_fhandle *);
++int nfs3svc_decode_sattrargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_sattrargs *);
+-int nfs3svc_decode_diropargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_diropargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_diropargs *);
+-int nfs3svc_decode_accessargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_accessargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_accessargs *);
+-int nfs3svc_decode_readargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_readargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_readargs *);
+-int nfs3svc_decode_writeargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_writeargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_writeargs *);
+-int nfs3svc_decode_createargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_createargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_createargs *);
+-int nfs3svc_decode_mkdirargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_mkdirargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_createargs *);
+-int nfs3svc_decode_mknodargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_mknodargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_mknodargs *);
+-int nfs3svc_decode_renameargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_renameargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_renameargs *);
+-int nfs3svc_decode_readlinkargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_readlinkargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_readlinkargs *);
+-int nfs3svc_decode_linkargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_linkargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_linkargs *);
+-int nfs3svc_decode_symlinkargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_symlinkargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_symlinkargs *);
+-int nfs3svc_decode_readdirargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_readdirargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_readdirargs *);
+-int nfs3svc_decode_readdirplusargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_readdirargs *);
+-int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *,
++int nfs3svc_decode_commitargs(struct svc_rqst *, __u32 *,
+ struct nfsd3_commitargs *);
+-int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *);
+-int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *,
++int nfs3svc_encode_voidres(struct svc_rqst *, __u32 *, void *);
++int nfs3svc_encode_attrstat(struct svc_rqst *, __u32 *,
+ struct nfsd3_attrstat *);
+-int nfs3svc_encode_wccstat(struct svc_rqst *, u32 *,
++int nfs3svc_encode_wccstat(struct svc_rqst *, __u32 *,
+ struct nfsd3_attrstat *);
+-int nfs3svc_encode_diropres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_diropres(struct svc_rqst *, __u32 *,
+ struct nfsd3_diropres *);
+-int nfs3svc_encode_accessres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_accessres(struct svc_rqst *, __u32 *,
+ struct nfsd3_accessres *);
+-int nfs3svc_encode_readlinkres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_readlinkres(struct svc_rqst *, __u32 *,
+ struct nfsd3_readlinkres *);
+-int nfs3svc_encode_readres(struct svc_rqst *, u32 *, struct nfsd3_readres *);
+-int nfs3svc_encode_writeres(struct svc_rqst *, u32 *, struct nfsd3_writeres *);
+-int nfs3svc_encode_createres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_readres(struct svc_rqst *, __u32 *, struct nfsd3_readres *);
++int nfs3svc_encode_writeres(struct svc_rqst *, __u32 *, struct nfsd3_writeres *);
++int nfs3svc_encode_createres(struct svc_rqst *, __u32 *,
+ struct nfsd3_diropres *);
+-int nfs3svc_encode_renameres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_renameres(struct svc_rqst *, __u32 *,
+ struct nfsd3_renameres *);
+-int nfs3svc_encode_linkres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_linkres(struct svc_rqst *, __u32 *,
+ struct nfsd3_linkres *);
+-int nfs3svc_encode_readdirres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_readdirres(struct svc_rqst *, __u32 *,
+ struct nfsd3_readdirres *);
+-int nfs3svc_encode_fsstatres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_fsstatres(struct svc_rqst *, __u32 *,
+ struct nfsd3_fsstatres *);
+-int nfs3svc_encode_fsinfores(struct svc_rqst *, u32 *,
++int nfs3svc_encode_fsinfores(struct svc_rqst *, __u32 *,
+ struct nfsd3_fsinfores *);
+-int nfs3svc_encode_pathconfres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_pathconfres(struct svc_rqst *, __u32 *,
+ struct nfsd3_pathconfres *);
+-int nfs3svc_encode_commitres(struct svc_rqst *, u32 *,
++int nfs3svc_encode_commitres(struct svc_rqst *, __u32 *,
+ struct nfsd3_commitres *);
+
+-int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
++int nfs3svc_release_fhandle(struct svc_rqst *, __u32 *,
+ struct nfsd3_attrstat *);
+-int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
++int nfs3svc_release_fhandle2(struct svc_rqst *, __u32 *,
+ struct nfsd3_fhandle_pair *);
+ int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
+ int namlen, loff_t offset, ino_t ino,
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr4.h linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr4.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/nfsd/xdr4.h 2004-08-18 13:16:07.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/nfsd/xdr4.h 2004-08-26 05:42:08.000000000 -0500
+@@ -42,9 +42,9 @@
+ #define NFSD4_MAX_TAGLEN 128
+ #define XDR_LEN(n) (((n) + 3) & ~3)
+
+-typedef u32 delegation_zero_t;
+-typedef u32 delegation_boot_t;
+-typedef u64 delegation_id_t;
++typedef __u32 delegation_zero_t;
++typedef __u32 delegation_boot_t;
++typedef __u64 delegation_id_t;
+
+ typedef struct {
+ delegation_zero_t ds_zero;
+@@ -53,46 +53,46 @@
+ } delegation_stateid_t;
+
+ struct nfsd4_change_info {
+- u32 atomic;
+- u32 before_ctime_sec;
+- u32 before_ctime_nsec;
+- u32 after_ctime_sec;
+- u32 after_ctime_nsec;
++ __u32 atomic;
++ __u32 before_ctime_sec;
++ __u32 before_ctime_nsec;
++ __u32 after_ctime_sec;
++ __u32 after_ctime_nsec;
+ };
+
+ struct nfsd4_access {
+- u32 ac_req_access; /* request */
+- u32 ac_supported; /* response */
+- u32 ac_resp_access; /* response */
++ __u32 ac_req_access; /* request */
++ __u32 ac_supported; /* response */
++ __u32 ac_resp_access; /* response */
+ };
+
+ struct nfsd4_close {
+- u32 cl_seqid; /* request */
++ __u32 cl_seqid; /* request */
+ stateid_t cl_stateid; /* request+response */
+ struct nfs4_stateowner * cl_stateowner; /* response */
+ };
+
+ struct nfsd4_commit {
+- u64 co_offset; /* request */
+- u32 co_count; /* request */
++ __u64 co_offset; /* request */
++ __u32 co_count; /* request */
+ nfs4_verifier co_verf; /* response */
+ };
+
+ struct nfsd4_create {
+- u32 cr_namelen; /* request */
++ __u32 cr_namelen; /* request */
+ char * cr_name; /* request */
+- u32 cr_type; /* request */
++ __u32 cr_type; /* request */
+ union { /* request */
+ struct {
+- u32 namelen;
++ __u32 namelen;
+ char *name;
+ } link; /* NF4LNK */
+ struct {
+- u32 specdata1;
+- u32 specdata2;
++ __u32 specdata1;
++ __u32 specdata2;
+ } dev; /* NF4BLK, NF4CHR */
+ } u;
+- u32 cr_bmval[2]; /* request */
++ __u32 cr_bmval[2]; /* request */
+ struct iattr cr_iattr; /* request */
+ struct nfsd4_change_info cr_cinfo; /* response */
+ };
+@@ -102,41 +102,41 @@
+ #define cr_specdata2 u.dev.specdata2
+
+ struct nfsd4_getattr {
+- u32 ga_bmval[2]; /* request */
++ __u32 ga_bmval[2]; /* request */
+ struct svc_fh *ga_fhp; /* response */
+ };
+
+ struct nfsd4_link {
+- u32 li_namelen; /* request */
++ __u32 li_namelen; /* request */
+ char * li_name; /* request */
+ struct nfsd4_change_info li_cinfo; /* response */
+ };
+
+ struct nfsd4_lock_denied {
+ struct nfs4_stateowner *ld_sop;
+- u64 ld_start;
+- u64 ld_length;
+- u32 ld_type;
++ __u64 ld_start;
++ __u64 ld_length;
++ __u32 ld_type;
+ };
+
+ struct nfsd4_lock {
+ /* request */
+- u32 lk_type;
+- u32 lk_reclaim; /* boolean */
+- u64 lk_offset;
+- u64 lk_length;
+- u32 lk_is_new;
++ __u32 lk_type;
++ __u32 lk_reclaim; /* boolean */
++ __u64 lk_offset;
++ __u64 lk_length;
++ __u32 lk_is_new;
+ union {
+ struct {
+- u32 open_seqid;
++ __u32 open_seqid;
+ stateid_t open_stateid;
+- u32 lock_seqid;
++ __u32 lock_seqid;
+ clientid_t clientid;
+ struct xdr_netobj owner;
+ } new;
+ struct {
+ stateid_t lock_stateid;
+- u32 lock_seqid;
++ __u32 lock_seqid;
+ } old;
+ } v;
+
+@@ -164,56 +164,56 @@
+
+
+ struct nfsd4_lockt {
+- u32 lt_type;
++ __u32 lt_type;
+ clientid_t lt_clientid;
+ struct xdr_netobj lt_owner;
+- u64 lt_offset;
+- u64 lt_length;
++ __u64 lt_offset;
++ __u64 lt_length;
+ struct nfs4_stateowner * lt_stateowner;
+ struct nfsd4_lock_denied lt_denied;
+ };
+
+
+ struct nfsd4_locku {
+- u32 lu_type;
+- u32 lu_seqid;
++ __u32 lu_type;
++ __u32 lu_seqid;
+ stateid_t lu_stateid;
+- u64 lu_offset;
+- u64 lu_length;
++ __u64 lu_offset;
++ __u64 lu_length;
+ struct nfs4_stateowner *lu_stateowner;
+ };
+
+
+ struct nfsd4_lookup {
+- u32 lo_len; /* request */
++ __u32 lo_len; /* request */
+ char * lo_name; /* request */
+ };
+
+ struct nfsd4_putfh {
+- u32 pf_fhlen; /* request */
++ __u32 pf_fhlen; /* request */
+ char *pf_fhval; /* request */
+ };
+
+ struct nfsd4_open {
+- u32 op_claim_type; /* request */
++ __u32 op_claim_type; /* request */
+ struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */
+- u32 op_delegate_type; /* request - CLAIM_PREV only */
++ __u32 op_delegate_type; /* request - CLAIM_PREV only */
+ delegation_stateid_t op_delegate_stateid; /* request - CLAIM_DELEGATE_CUR only */
+- u32 op_create; /* request */
+- u32 op_createmode; /* request */
+- u32 op_bmval[2]; /* request */
++ __u32 op_create; /* request */
++ __u32 op_createmode; /* request */
++ __u32 op_bmval[2]; /* request */
+ union { /* request */
+ struct iattr iattr; /* UNCHECKED4,GUARDED4 */
+ nfs4_verifier verf; /* EXCLUSIVE4 */
+ } u;
+ clientid_t op_clientid; /* request */
+ struct xdr_netobj op_owner; /* request */
+- u32 op_seqid; /* request */
+- u32 op_share_access; /* request */
+- u32 op_share_deny; /* request */
++ __u32 op_seqid; /* request */
++ __u32 op_share_access; /* request */
++ __u32 op_share_deny; /* request */
+ stateid_t op_stateid; /* response */
+ struct nfsd4_change_info op_cinfo; /* response */
+- u32 op_rflags; /* response */
++ __u32 op_rflags; /* response */
+ int op_truncate; /* used during processing */
+ struct nfs4_stateowner *op_stateowner; /* used during processing */
+
+@@ -223,24 +223,24 @@
+
+ struct nfsd4_open_confirm {
+ stateid_t oc_req_stateid /* request */;
+- u32 oc_seqid /* request */;
++ __u32 oc_seqid /* request */;
+ stateid_t oc_resp_stateid /* response */;
+ struct nfs4_stateowner * oc_stateowner; /* response */
+ };
+
+ struct nfsd4_open_downgrade {
+ stateid_t od_stateid;
+- u32 od_seqid;
+- u32 od_share_access;
+- u32 od_share_deny;
++ __u32 od_seqid;
++ __u32 od_share_access;
++ __u32 od_share_deny;
+ struct nfs4_stateowner *od_stateowner;
+ };
+
+
+ struct nfsd4_read {
+ stateid_t rd_stateid; /* request */
+- u64 rd_offset; /* request */
+- u32 rd_length; /* request */
++ __u64 rd_offset; /* request */
++ __u32 rd_length; /* request */
+ struct kvec rd_iov[RPCSVC_MAXPAGES];
+ int rd_vlen;
+
+@@ -249,18 +249,18 @@
+ };
+
+ struct nfsd4_readdir {
+- u64 rd_cookie; /* request */
++ __u64 rd_cookie; /* request */
+ nfs4_verifier rd_verf; /* request */
+- u32 rd_dircount; /* request */
+- u32 rd_maxcount; /* request */
+- u32 rd_bmval[2]; /* request */
++ __u32 rd_dircount; /* request */
++ __u32 rd_maxcount; /* request */
++ __u32 rd_bmval[2]; /* request */
+ struct svc_rqst *rd_rqstp; /* response */
+ struct svc_fh * rd_fhp; /* response */
+
+ struct readdir_cd common;
+- u32 * buffer;
++ __u32 * buffer;
+ int buflen;
+- u32 * offset;
++ __u32 * offset;
+ };
+
+ struct nfsd4_release_lockowner {
+@@ -273,15 +273,15 @@
+ };
+
+ struct nfsd4_remove {
+- u32 rm_namelen; /* request */
++ __u32 rm_namelen; /* request */
+ char * rm_name; /* request */
+ struct nfsd4_change_info rm_cinfo; /* response */
+ };
+
+ struct nfsd4_rename {
+- u32 rn_snamelen; /* request */
++ __u32 rn_snamelen; /* request */
+ char * rn_sname; /* request */
+- u32 rn_tnamelen; /* request */
++ __u32 rn_tnamelen; /* request */
+ char * rn_tname; /* request */
+ struct nfsd4_change_info rn_sinfo; /* response */
+ struct nfsd4_change_info rn_tinfo; /* response */
+@@ -289,20 +289,20 @@
+
+ struct nfsd4_setattr {
+ stateid_t sa_stateid; /* request */
+- u32 sa_bmval[2]; /* request */
++ __u32 sa_bmval[2]; /* request */
+ struct iattr sa_iattr; /* request */
+ };
+
+ struct nfsd4_setclientid {
+ nfs4_verifier se_verf; /* request */
+- u32 se_namelen; /* request */
++ __u32 se_namelen; /* request */
+ char * se_name; /* request */
+- u32 se_callback_prog; /* request */
+- u32 se_callback_netid_len; /* request */
++ __u32 se_callback_prog; /* request */
++ __u32 se_callback_netid_len; /* request */
+ char * se_callback_netid_val; /* request */
+- u32 se_callback_addr_len; /* request */
++ __u32 se_callback_addr_len; /* request */
+ char * se_callback_addr_val; /* request */
+- u32 se_callback_ident; /* request */
++ __u32 se_callback_ident; /* request */
+ clientid_t se_clientid; /* response */
+ nfs4_verifier se_confirm; /* response */
+ };
+@@ -314,21 +314,21 @@
+
+ /* also used for NVERIFY */
+ struct nfsd4_verify {
+- u32 ve_bmval[2]; /* request */
+- u32 ve_attrlen; /* request */
++ __u32 ve_bmval[2]; /* request */
++ __u32 ve_attrlen; /* request */
+ char * ve_attrval; /* request */
+ };
+
+ struct nfsd4_write {
+ stateid_t wr_stateid; /* request */
+- u64 wr_offset; /* request */
+- u32 wr_stable_how; /* request */
+- u32 wr_buflen; /* request */
++ __u64 wr_offset; /* request */
++ __u32 wr_stable_how; /* request */
++ __u32 wr_buflen; /* request */
+ struct kvec wr_vec[RPCSVC_MAXPAGES]; /* request */
+ int wr_vlen;
+
+- u32 wr_bytes_written; /* response */
+- u32 wr_how_written; /* response */
++ __u32 wr_bytes_written; /* response */
++ __u32 wr_how_written; /* response */
+ nfs4_verifier wr_verifier; /* response */
+ };
+
+@@ -370,12 +370,12 @@
+
+ struct nfsd4_compoundargs {
+ /* scratch variables for XDR decode */
+- u32 * p;
+- u32 * end;
++ __u32 * p;
++ __u32 * end;
+ struct page ** pagelist;
+ int pagelen;
+- u32 tmp[8];
+- u32 * tmpp;
++ __u32 tmp[8];
++ __u32 * tmpp;
+ struct tmpbuf {
+ struct tmpbuf *next;
+ void (*release)(const void *);
+@@ -384,25 +384,25 @@
+
+ struct svc_rqst *rqstp;
+
+- u32 taglen;
++ __u32 taglen;
+ char * tag;
+- u32 minorversion;
+- u32 opcnt;
++ __u32 minorversion;
++ __u32 opcnt;
+ struct nfsd4_op *ops;
+ struct nfsd4_op iops[8];
+ };
+
+ struct nfsd4_compoundres {
+ /* scratch variables for XDR encode */
+- u32 * p;
+- u32 * end;
++ __u32 * p;
++ __u32 * end;
+ struct xdr_buf * xbuf;
+ struct svc_rqst * rqstp;
+
+- u32 taglen;
++ __u32 taglen;
+ char * tag;
+- u32 opcnt;
+- u32 * tagp; /* where to encode tag and opcount */
++ __u32 opcnt;
++ __u32 * tagp; /* where to encode tag and opcount */
+ };
+
+ #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
+@@ -418,16 +418,16 @@
+ cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec;
+ }
+
+-int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *);
+-int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *,
++int nfs4svc_encode_voidres(struct svc_rqst *, __u32 *, void *);
++int nfs4svc_decode_compoundargs(struct svc_rqst *, __u32 *,
+ struct nfsd4_compoundargs *);
+-int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *,
++int nfs4svc_encode_compoundres(struct svc_rqst *, __u32 *,
+ struct nfsd4_compoundres *);
+ void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
+ void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
+ int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+- struct dentry *dentry, u32 *buffer, int *countp,
+- u32 *bmval, struct svc_rqst *);
++ struct dentry *dentry, __u32 *buffer, int *countp,
++ __u32 *bmval, struct svc_rqst *);
+ extern int nfsd4_setclientid(struct svc_rqst *rqstp,
+ struct nfsd4_setclientid *setclid);
+ extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/pmu.h linux-libc-headers-2.6.8.0/include/linux/pmu.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/pmu.h 2004-01-17 17:04:31.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/pmu.h 2004-08-26 05:42:08.000000000 -0500
+@@ -120,15 +120,15 @@
+
+ /* no param */
+ #define PMU_IOC_SLEEP _IO('B', 0)
+-/* out param: u32* backlight value: 0 to 15 */
++/* out param: __u32* backlight value: 0 to 15 */
+ #define PMU_IOC_GET_BACKLIGHT _IOR('B', 1, size_t)
+-/* in param: u32 backlight value: 0 to 15 */
++/* in param: __u32 backlight value: 0 to 15 */
+ #define PMU_IOC_SET_BACKLIGHT _IOW('B', 2, size_t)
+-/* out param: u32* PMU model */
++/* out param: __u32* PMU model */
+ #define PMU_IOC_GET_MODEL _IOR('B', 3, size_t)
+-/* out param: u32* has_adb: 0 or 1 */
++/* out param: __u32* has_adb: 0 or 1 */
+ #define PMU_IOC_HAS_ADB _IOR('B', 4, size_t)
+-/* out param: u32* can_sleep: 0 or 1 */
++/* out param: __u32* can_sleep: 0 or 1 */
+ #define PMU_IOC_CAN_SLEEP _IOR('B', 5, size_t)
+ /* no param, but historically was _IOR('B', 6, 0), meaning 4 bytes */
+ #define PMU_IOC_GRAB_BACKLIGHT _IOR('B', 6, size_t)
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/reiserfs_fs.h linux-libc-headers-2.6.8.0/include/linux/reiserfs_fs.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/reiserfs_fs.h 2004-08-18 13:16:04.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/reiserfs_fs.h 2004-08-26 13:26:06.000000000 -0500
+@@ -1821,7 +1821,7 @@
+ * to use for a new object underneat it. The locality is returned
+ * in disk byte order (le).
+ */
+-u32 reiserfs_choose_packing(struct inode *dir);
++__u32 reiserfs_choose_packing(struct inode *dir);
+
+ int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
+ void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/scx200_gpio.h linux-libc-headers-2.6.8.0/include/linux/scx200_gpio.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/scx200_gpio.h 2004-01-17 17:04:32.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/scx200_gpio.h 2004-08-26 13:26:01.000000000 -0500
+@@ -1,5 +1,5 @@
+
+-u32 scx200_gpio_configure(int index, u32 set, u32 clear);
++__u32 scx200_gpio_configure(int index, __u32 set, __u32 clear);
+ void scx200_gpio_dump(unsigned index);
+
+ extern unsigned scx200_gpio_base;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sdladrv.h linux-libc-headers-2.6.8.0/include/linux/sdladrv.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sdladrv.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/sdladrv.h 2004-08-26 05:42:08.000000000 -0500
+@@ -55,8 +55,8 @@
+ extern int sdla_inten (sdlahw_t* hw);
+ extern int sdla_intde (sdlahw_t* hw);
+ extern int sdla_intack (sdlahw_t* hw);
+-extern void S514_intack (sdlahw_t* hw, u32 int_status);
+-extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
++extern void S514_intack (sdlahw_t* hw, __u32 int_status);
++extern void read_S514_int_stat (sdlahw_t* hw, __u32* int_status);
+ extern int sdla_intr (sdlahw_t* hw);
+ extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
+ extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf,
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/selection.h linux-libc-headers-2.6.8.0/include/linux/selection.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/selection.h 2004-06-23 16:52:56.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/selection.h 2004-08-26 05:42:08.000000000 -0500
+@@ -32,14 +32,14 @@
+ extern int default_blu[];
+
+ extern unsigned short *screen_pos(int currcons, int w_offset, int viewed);
+-extern u16 screen_glyph(int currcons, int offset);
++extern __u16 screen_glyph(int currcons, int offset);
+ extern void complement_pos(int currcons, int offset);
+ extern void invert_screen(int currcons, int offset, int count, int shift);
+
+ extern void getconsxy(int currcons, unsigned char *p);
+ extern void putconsxy(int currcons, unsigned char *p);
+
+-extern u16 vcs_scr_readw(int currcons, const u16 *org);
+-extern void vcs_scr_writew(int currcons, u16 val, u16 *org);
++extern __u16 vcs_scr_readw(int currcons, const __u16 *org);
++extern void vcs_scr_writew(int currcons, __u16 val, __u16 *org);
+
+ #endif
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/serialP.h linux-libc-headers-2.6.8.0/include/linux/serialP.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/serialP.h 2004-08-18 13:16:04.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/serialP.h 2004-08-26 05:42:08.000000000 -0500
+@@ -39,8 +39,8 @@
+ int xmit_fifo_size;
+ int custom_divisor;
+ int count;
+- u8 *iomem_base;
+- u16 iomem_reg_shift;
++ __u8 *iomem_base;
++ __u16 iomem_reg_shift;
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+ struct async_icount icount;
+@@ -75,8 +75,8 @@
+ int blocked_open; /* # of blocked opens */
+ struct circ_buf xmit;
+ spinlock_t xmit_lock;
+- u8 *iomem_base;
+- u16 iomem_reg_shift;
++ __u8 *iomem_base;
++ __u16 iomem_reg_shift;
+ int io_type;
+ struct work_struct work;
+ struct tasklet_struct tlet;
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/clnt.h linux-libc-headers-2.6.8.0/include/linux/sunrpc/clnt.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/clnt.h 2004-02-29 10:36:05.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/sunrpc/clnt.h 2004-08-26 05:42:08.000000000 -0500
+@@ -36,7 +36,7 @@
+ atomic_t cl_users; /* number of references */
+ struct rpc_xprt * cl_xprt; /* transport */
+ struct rpc_procinfo * cl_procinfo; /* procedure info */
+- u32 cl_maxproc; /* max procedure number */
++ __u32 cl_maxproc; /* max procedure number */
+
+ char * cl_server; /* server machine name */
+ char * cl_protname; /* protocol name */
+@@ -75,7 +75,7 @@
+ #define RPC_MAXVERSION 4
+ struct rpc_program {
+ char * name; /* protocol name */
+- u32 number; /* program number */
++ __u32 number; /* program number */
+ unsigned int nrvers; /* number of versions */
+ struct rpc_version ** version; /* version array */
+ struct rpc_stat * stats; /* statistics */
+@@ -83,7 +83,7 @@
+ };
+
+ struct rpc_version {
+- u32 number; /* version number */
++ __u32 number; /* version number */
+ unsigned int nrprocs; /* number of procs */
+ struct rpc_procinfo * procs; /* procedure array */
+ };
+@@ -92,7 +92,7 @@
+ * Procedure information
+ */
+ struct rpc_procinfo {
+- u32 p_proc; /* RPC procedure number */
++ __u32 p_proc; /* RPC procedure number */
+ kxdrproc_t p_encode; /* XDR encode function */
+ kxdrproc_t p_decode; /* XDR decode function */
+ unsigned int p_bufsiz; /* req. buffer size */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/gss_asn1.h linux-libc-headers-2.6.8.0/include/linux/sunrpc/gss_asn1.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/gss_asn1.h 2004-06-23 16:52:58.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/sunrpc/gss_asn1.h 2004-08-26 13:26:25.000000000 -0500
+@@ -64,14 +64,14 @@
+ (((o1)->len == (o2)->len) && \
+ (memcmp((o1)->data,(o2)->data,(int) (o1)->len) == 0))
+
+-u32 g_verify_token_header(
++__u32 g_verify_token_header(
+ struct xdr_netobj *mech,
+ int *body_size,
+ unsigned char **buf_in,
+ int tok_type,
+ int toksize);
+
+-u32 g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf);
++__u32 g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf);
+
+ int g_token_size(
+ struct xdr_netobj *mech,
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/gss_krb5.h linux-libc-headers-2.6.8.0/include/linux/sunrpc/gss_krb5.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/gss_krb5.h 2004-06-23 16:52:58.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/sunrpc/gss_krb5.h 2004-08-26 13:26:21.000000000 -0500
+@@ -46,8 +46,8 @@
+ int sealalg;
+ struct crypto_tfm *enc;
+ struct crypto_tfm *seq;
+- s32 endtime;
+- u32 seq_send;
++ __s32 endtime;
++ __u32 seq_send;
+ struct xdr_netobj mech_used;
+ };
+
+@@ -112,35 +112,35 @@
+ #define ENCTYPE_DES3_CBC_SHA1 0x0010
+ #define ENCTYPE_UNKNOWN 0x01ff
+
+-s32
+-make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
++__s32
++make_checksum(__s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+ struct xdr_netobj *cksum);
+
+-u32
++__u32
+ krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
+ struct xdr_buf *input_message_buffer,
+ struct xdr_netobj *output_message_buffer, int toktype);
+
+-u32
++__u32
+ krb5_read_token(struct krb5_ctx *context_handle,
+ struct xdr_netobj *input_token_buffer,
+ struct xdr_buf *message_buffer,
+ int *qop_state, int toktype);
+
+-u32
++__u32
+ krb5_encrypt(struct crypto_tfm * key,
+ void *iv, void *in, void *out, int length);
+
+-u32
++__u32
+ krb5_decrypt(struct crypto_tfm * key,
+ void *iv, void *in, void *out, int length);
+
+-s32
++__s32
+ krb5_make_seq_num(struct crypto_tfm * key,
+ int direction,
+- s32 seqnum, unsigned char *cksum, unsigned char *buf);
++ __s32 seqnum, unsigned char *cksum, unsigned char *buf);
+
+-s32
++__s32
+ krb5_get_seq_num(struct crypto_tfm * key,
+ unsigned char *cksum,
+- unsigned char *buf, int *direction, s32 * seqnum);
++ unsigned char *buf, int *direction, __s32 * seqnum);
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/svc.h linux-libc-headers-2.6.8.0/include/linux/sunrpc/svc.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/svc.h 2004-08-18 13:16:07.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/sunrpc/svc.h 2004-08-26 05:42:08.000000000 -0500
+@@ -75,20 +75,20 @@
+ */
+ #define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2)
+
+-static inline u32 svc_getu32(struct kvec *iov)
++static inline __u32 svc_getu32(struct kvec *iov)
+ {
+- u32 val, *vp;
++ __u32 val, *vp;
+ vp = iov->iov_base;
+ val = *vp++;
+ iov->iov_base = (void*)vp;
+- iov->iov_len -= sizeof(u32);
++ iov->iov_len -= sizeof(__u32);
+ return val;
+ }
+-static inline void svc_putu32(struct kvec *iov, u32 val)
++static inline void svc_putu32(struct kvec *iov, __u32 val)
+ {
+- u32 *vp = iov->iov_base + iov->iov_len;
++ __u32 *vp = iov->iov_base + iov->iov_len;
+ *vp = val;
+- iov->iov_len += sizeof(u32);
++ iov->iov_len += sizeof(__u32);
+ }
+
+
+@@ -119,11 +119,11 @@
+ short rq_arghi; /* pages available in argument page list */
+ short rq_resused; /* pages used for result */
+
+- u32 rq_xid; /* transmission id */
+- u32 rq_prog; /* program number */
+- u32 rq_vers; /* program version */
+- u32 rq_proc; /* procedure number */
+- u32 rq_prot; /* IP protocol */
++ __u32 rq_xid; /* transmission id */
++ __u32 rq_prog; /* program number */
++ __u32 rq_vers; /* program version */
++ __u32 rq_proc; /* procedure number */
++ __u32 rq_prot; /* IP protocol */
+ unsigned short
+ rq_secure : 1; /* secure port */
+
+@@ -156,7 +156,7 @@
+ * Check buffer bounds after decoding arguments
+ */
+ static inline int
+-xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
++xdr_argsize_check(struct svc_rqst *rqstp, __u32 *p)
+ {
+ char *cp = (char *)p;
+ struct kvec *vec = &rqstp->rq_arg.head[0];
+@@ -164,7 +164,7 @@
+ }
+
+ static inline int
+-xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
++xdr_ressize_check(struct svc_rqst *rqstp, __u32 *p)
+ {
+ struct kvec *vec = &rqstp->rq_res.head[0];
+ char *cp = (char*)p;
+@@ -220,19 +220,19 @@
+ }
+
+ struct svc_deferred_req {
+- u32 prot; /* protocol (UDP or TCP) */
++ __u32 prot; /* protocol (UDP or TCP) */
+ struct sockaddr_in addr;
+ struct svc_sock *svsk; /* where reply must go */
+ struct cache_deferred_req handle;
+ int argslen;
+- u32 args[0];
++ __u32 args[0];
+ };
+
+ /*
+ * RPC program
+ */
+ struct svc_program {
+- u32 pg_prog; /* program number */
++ __u32 pg_prog; /* program number */
+ unsigned int pg_lovers; /* lowest version */
+ unsigned int pg_hivers; /* lowest version */
+ unsigned int pg_nvers; /* number of versions */
+@@ -246,16 +246,16 @@
+ * RPC program version
+ */
+ struct svc_version {
+- u32 vs_vers; /* version number */
+- u32 vs_nproc; /* number of procedures */
++ __u32 vs_vers; /* version number */
++ __u32 vs_nproc; /* number of procedures */
+ struct svc_procedure * vs_proc; /* per-procedure info */
+- u32 vs_xdrsize; /* xdrsize needed for this version */
++ __u32 vs_xdrsize; /* xdrsize needed for this version */
+
+ /* Override dispatch function (e.g. when caching replies).
+ * A return value of 0 means drop the request.
+ * vs_dispatch == NULL means use default dispatcher.
+ */
+- int (*vs_dispatch)(struct svc_rqst *, u32 *);
++ int (*vs_dispatch)(struct svc_rqst *, __u32 *);
+ };
+
+ /*
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/xprt.h linux-libc-headers-2.6.8.0/include/linux/sunrpc/xprt.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sunrpc/xprt.h 2004-06-23 16:52:58.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/sunrpc/xprt.h 2004-08-26 05:42:08.000000000 -0500
+@@ -93,7 +93,7 @@
+ __u32 rq_xid; /* request XID */
+ int rq_cong; /* has incremented xprt->cong */
+ int rq_received; /* receive completed */
+- u32 rq_seqno; /* gss seq no. used on req. */
++ __u32 rq_seqno; /* gss seq no. used on req. */
+
+ struct list_head rq_list;
+
+@@ -106,13 +106,13 @@
+ /*
+ * For authentication (e.g. auth_des)
+ */
+- u32 rq_creddata[2];
++ __u32 rq_creddata[2];
+
+ /*
+ * Partial send handling
+ */
+
+- u32 rq_bytes_sent; /* Bytes we have sent */
++ __u32 rq_bytes_sent; /* Bytes we have sent */
+
+ unsigned long rq_xtime; /* when transmitted */
+ int rq_ntrans;
+@@ -160,7 +160,7 @@
+ /*
+ * State of TCP reply receive stuff
+ */
+- u32 tcp_recm, /* Fragment header */
++ __u32 tcp_recm, /* Fragment header */
+ tcp_xid, /* Current XID */
+ tcp_reclen, /* fragment length */
+ tcp_offset; /* fragment offset */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/suspend.h linux-libc-headers-2.6.8.0/include/linux/suspend.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/suspend.h 2004-08-18 13:16:05.000000000 -0500
++++ linux-libc-headers-2.6.8.0/include/linux/suspend.h 2004-08-26 05:42:08.000000000 -0500
+@@ -23,7 +23,7 @@
+ #define SWAP_FILENAME_MAXLENGTH 32
+
+ struct suspend_header {
+- u32 version_code;
++ __u32 version_code;
+ unsigned long num_physpages;
+ char machine[8];
+ char version[20];
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sysdev.h linux-libc-headers-2.6.8.0/include/linux/sysdev.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sysdev.h 2004-03-28 07:52:11.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/sysdev.h 2004-08-26 05:42:08.000000000 -0500
+@@ -31,7 +31,7 @@
+
+ /* Default operations for these types of devices */
+ int (*shutdown)(struct sys_device *);
+- int (*suspend)(struct sys_device *, u32 state);
++ int (*suspend)(struct sys_device *, __u32 state);
+ int (*resume)(struct sys_device *);
+ struct kset kset;
+ };
+@@ -50,7 +50,7 @@
+ int (*add)(struct sys_device *);
+ int (*remove)(struct sys_device *);
+ int (*shutdown)(struct sys_device *);
+- int (*suspend)(struct sys_device *, u32 state);
++ int (*suspend)(struct sys_device *, __u32 state);
+ int (*resume)(struct sys_device *);
+ };
+
+@@ -65,7 +65,7 @@
+ */
+
+ struct sys_device {
+- u32 id;
++ __u32 id;
+ struct sysdev_class * cls;
+ struct kobject kobj;
+ };
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/sysv_fs.h linux-libc-headers-2.6.8.0/include/linux/sysv_fs.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/sysv_fs.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/sysv_fs.h 2004-08-26 05:42:08.000000000 -0500
+@@ -9,12 +9,12 @@
+
+
+ /* inode numbers are 16 bit */
+-typedef u16 sysv_ino_t;
++typedef __u16 sysv_ino_t;
+
+ /* Block numbers are 24 bit, sometimes stored in 32 bit.
+ On Coherent FS, they are always stored in PDP-11 manner: the least
+ significant 16 bits come last. */
+-typedef u32 sysv_zone_t;
++typedef __u32 sysv_zone_t;
+
+ /* 0 is non-existent */
+ #define SYSV_BADBL_INO 1 /* inode of bad blocks file */
+@@ -25,29 +25,29 @@
+ #define XENIX_NICINOD 100 /* number of inode cache entries */
+ #define XENIX_NICFREE 100 /* number of free block list chunk entries */
+ struct xenix_super_block {
+- u16 s_isize; /* index of first data zone */
+- u32 s_fsize __packed2__; /* total number of zones of this fs */
++ __u16 s_isize; /* index of first data zone */
++ __u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+- u16 s_nfree; /* number of free blocks in s_free, <= XENIX_NICFREE */
+- u32 s_free[XENIX_NICFREE]; /* first free block list chunk */
++ __u16 s_nfree; /* number of free blocks in s_free, <= XENIX_NICFREE */
++ __u32 s_free[XENIX_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+- u16 s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
++ __u16 s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+ sysv_ino_t s_inode[XENIX_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+- u32 s_time __packed2__; /* time of last super block update */
+- u32 s_tfree __packed2__; /* total number of free zones */
+- u16 s_tinode; /* total number of free inodes */
+- s16 s_dinfo[4]; /* device information ?? */
++ __u32 s_time __packed2__; /* time of last super block update */
++ __u32 s_tfree __packed2__; /* total number of free zones */
++ __u16 s_tinode; /* total number of free inodes */
++ __s16 s_dinfo[4]; /* device information ?? */
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+ char s_clean; /* set to 0x46 when filesystem is properly unmounted */
+ char s_fill[371];
+- s32 s_magic; /* version of file system */
+- s32 s_type; /* type of file system: 1 for 512 byte blocks
++ __s32 s_magic; /* version of file system */
++ __s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks
+ 3 for 2048 byte blocks */
+
+@@ -63,61 +63,61 @@
+
+ /* SystemV4 super-block data on disk */
+ struct sysv4_super_block {
+- u16 s_isize; /* index of first data zone */
+- u16 s_pad0;
+- u32 s_fsize; /* total number of zones of this fs */
++ __u16 s_isize; /* index of first data zone */
++ __u16 s_pad0;
++ __u32 s_fsize; /* total number of zones of this fs */
+ /* the start of the free block list: */
+- u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
+- u16 s_pad1;
+- u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
++ __u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
++ __u16 s_pad1;
++ __u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+- u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+- u16 s_pad2;
++ __u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
++ __u16 s_pad2;
+ sysv_ino_t s_inode[SYSV_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+- u32 s_time; /* time of last super block update */
+- s16 s_dinfo[4]; /* device information ?? */
+- u32 s_tfree; /* total number of free zones */
+- u16 s_tinode; /* total number of free inodes */
+- u16 s_pad3;
++ __u32 s_time; /* time of last super block update */
++ __s16 s_dinfo[4]; /* device information ?? */
++ __u32 s_tfree; /* total number of free zones */
++ __u16 s_tinode; /* total number of free inodes */
++ __u16 s_pad3;
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+- s32 s_fill[12];
+- s32 s_state; /* file system state: 0x7c269d38-s_time means clean */
+- s32 s_magic; /* version of file system */
+- s32 s_type; /* type of file system: 1 for 512 byte blocks
++ __s32 s_fill[12];
++ __s32 s_state; /* file system state: 0x7c269d38-s_time means clean */
++ __s32 s_magic; /* version of file system */
++ __s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks */
+ };
+
+ /* SystemV2 super-block data on disk */
+ struct sysv2_super_block {
+- u16 s_isize; /* index of first data zone */
+- u32 s_fsize __packed2__; /* total number of zones of this fs */
++ __u16 s_isize; /* index of first data zone */
++ __u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+- u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
+- u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
++ __u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
++ __u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+- u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
++ __u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+ sysv_ino_t s_inode[SYSV_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+- u32 s_time __packed2__; /* time of last super block update */
+- s16 s_dinfo[4]; /* device information ?? */
+- u32 s_tfree __packed2__; /* total number of free zones */
+- u16 s_tinode; /* total number of free inodes */
++ __u32 s_time __packed2__; /* time of last super block update */
++ __s16 s_dinfo[4]; /* device information ?? */
++ __u32 s_tfree __packed2__; /* total number of free zones */
++ __u16 s_tinode; /* total number of free inodes */
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+- s32 s_fill[14];
+- s32 s_state; /* file system state: 0xcb096f43 means clean */
+- s32 s_magic; /* version of file system */
+- s32 s_type; /* type of file system: 1 for 512 byte blocks
++ __s32 s_fill[14];
++ __s32 s_state; /* file system state: 0xcb096f43 means clean */
++ __s32 s_magic; /* version of file system */
++ __s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks */
+ };
+
+@@ -125,25 +125,25 @@
+ #define V7_NICINOD 100 /* number of inode cache entries */
+ #define V7_NICFREE 50 /* number of free block list chunk entries */
+ struct v7_super_block {
+- u16 s_isize; /* index of first data zone */
+- u32 s_fsize __packed2__; /* total number of zones of this fs */
++ __u16 s_isize; /* index of first data zone */
++ __u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+- u16 s_nfree; /* number of free blocks in s_free, <= V7_NICFREE */
+- u32 s_free[V7_NICFREE]; /* first free block list chunk */
++ __u16 s_nfree; /* number of free blocks in s_free, <= V7_NICFREE */
++ __u32 s_free[V7_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+- u16 s_ninode; /* number of free inodes in s_inode, <= V7_NICINOD */
++ __u16 s_ninode; /* number of free inodes in s_inode, <= V7_NICINOD */
+ sysv_ino_t s_inode[V7_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux or V7: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+- u32 s_time __packed2__; /* time of last super block update */
++ __u32 s_time __packed2__; /* time of last super block update */
+ /* the following fields are not maintained by V7: */
+- u32 s_tfree __packed2__; /* total number of free zones */
+- u16 s_tinode; /* total number of free inodes */
+- u16 s_m; /* interleave factor */
+- u16 s_n; /* interleave factor */
++ __u32 s_tfree __packed2__; /* total number of free zones */
++ __u16 s_tinode; /* total number of free inodes */
++ __u16 s_m; /* interleave factor */
++ __u16 s_n; /* interleave factor */
+ char s_fname[6]; /* file system name */
+ char s_fpack[6]; /* file system pack name */
+ };
+@@ -152,41 +152,41 @@
+ #define COH_NICINOD 100 /* number of inode cache entries */
+ #define COH_NICFREE 64 /* number of free block list chunk entries */
+ struct coh_super_block {
+- u16 s_isize; /* index of first data zone */
+- u32 s_fsize __packed2__; /* total number of zones of this fs */
++ __u16 s_isize; /* index of first data zone */
++ __u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+- u16 s_nfree; /* number of free blocks in s_free, <= COH_NICFREE */
+- u32 s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
++ __u16 s_nfree; /* number of free blocks in s_free, <= COH_NICFREE */
++ __u32 s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+ /* the cache of free inodes: */
+- u16 s_ninode; /* number of free inodes in s_inode, <= COH_NICINOD */
++ __u16 s_ninode; /* number of free inodes in s_inode, <= COH_NICINOD */
+ sysv_ino_t s_inode[COH_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+- u32 s_time __packed2__; /* time of last super block update */
+- u32 s_tfree __packed2__; /* total number of free zones */
+- u16 s_tinode; /* total number of free inodes */
+- u16 s_interleave_m; /* interleave factor */
+- u16 s_interleave_n;
++ __u32 s_time __packed2__; /* time of last super block update */
++ __u32 s_tfree __packed2__; /* total number of free zones */
++ __u16 s_tinode; /* total number of free inodes */
++ __u16 s_interleave_m; /* interleave factor */
++ __u16 s_interleave_n;
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+- u32 s_unique; /* zero, not used */
++ __u32 s_unique; /* zero, not used */
+ };
+
+ /* SystemV/Coherent inode data on disk */
+ struct sysv_inode {
+- u16 i_mode;
+- u16 i_nlink;
+- u16 i_uid;
+- u16 i_gid;
+- u32 i_size;
+- u8 i_data[3*(10+1+1+1)];
+- u8 i_gen;
+- u32 i_atime; /* time of last access */
+- u32 i_mtime; /* time of last modification */
+- u32 i_ctime; /* time of creation */
++ __u16 i_mode;
++ __u16 i_nlink;
++ __u16 i_uid;
++ __u16 i_gid;
++ __u32 i_size;
++ __u8 i_data[3*(10+1+1+1)];
++ __u8 i_gen;
++ __u32 i_atime; /* time of last access */
++ __u32 i_mtime; /* time of last modification */
++ __u32 i_ctime; /* time of creation */
+ };
+
+ /* SystemV/Coherent directory entry on disk */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/tiocl.h linux-libc-headers-2.6.8.0/include/linux/tiocl.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/tiocl.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/tiocl.h 2004-08-26 05:42:08.000000000 -0500
+@@ -23,7 +23,7 @@
+
+ #define TIOCL_SELLOADLUT 5
+ /* set characters to be considered alphabetic when selecting */
+- /* u32[8] bit array, 4 bytes-aligned with type */
++ /* __u32[8] bit array, 4 bytes-aligned with type */
+
+ /* these two don't return a value: they write it back in the type */
+ #define TIOCL_GETSHIFTSTATE 6 /* write shift state */
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/umem.h linux-libc-headers-2.6.8.0/include/linux/umem.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/umem.h 2003-12-15 12:46:58.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/umem.h 2004-08-26 05:42:08.000000000 -0500
+@@ -110,19 +110,19 @@
+ #define DMA_WRITE_TO_HOST 1
+
+ struct mm_dma_desc {
+- u64 pci_addr;
+- u64 local_addr;
+- u32 transfer_size;
+- u32 zero1;
+- u64 next_desc_addr;
+- u64 sem_addr;
+- u32 control_bits;
+- u32 zero2;
++ __u64 pci_addr;
++ __u64 local_addr;
++ __u32 transfer_size;
++ __u32 zero1;
++ __u64 next_desc_addr;
++ __u64 sem_addr;
++ __u32 control_bits;
++ __u32 zero2;
+
+ dma_addr_t data_dma_handle;
+
+ /* Copy of the bits */
+- u64 sem_control_bits;
++ __u64 sem_control_bits;
+ } __attribute__((aligned(8)));
+
+ #define PCI_VENDOR_ID_MICRO_MEMORY 0x1332
+diff -urN linux-libc-headers-2.6.8.0-dist/include/linux/vt_buffer.h linux-libc-headers-2.6.8.0/include/linux/vt_buffer.h
+--- linux-libc-headers-2.6.8.0-dist/include/linux/vt_buffer.h 2004-01-17 17:04:33.000000000 -0600
++++ linux-libc-headers-2.6.8.0/include/linux/vt_buffer.h 2004-08-26 05:42:08.000000000 -0500
+@@ -28,7 +28,7 @@
+ #endif
+
+ #ifndef VT_BUF_HAVE_MEMSETW
+-static inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
++static inline void scr_memsetw(__u16 *s, __u16 c, unsigned int count)
+ {
+ count /= 2;
+ while (count--)
+@@ -37,7 +37,7 @@
+ #endif
+
+ #ifndef VT_BUF_HAVE_MEMCPYW
+-static inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
++static inline void scr_memcpyw(__u16 *d, const __u16 *s, unsigned int count)
+ {
+ count /= 2;
+ while (count--)
+@@ -46,7 +46,7 @@
+ #endif
+
+ #ifndef VT_BUF_HAVE_MEMMOVEW
+-static inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
++static inline void scr_memmovew(__u16 *d, const __u16 *s, unsigned int count)
+ {
+ if (d < s)
+ scr_memcpyw(d, s, count);
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.9-nios2nommu.patch.conditional b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.9-nios2nommu.patch.conditional
new file mode 100644
index 0000000000..b828b3bb3f
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/linux-libc-headers-2.6.9-nios2nommu.patch.conditional
@@ -0,0 +1,12925 @@
+--- linux/include/asm-generic/bitops.h
++++ linux/include/asm-generic/bitops.h
+@@ -0,0 +1,81 @@
++#ifndef _ASM_GENERIC_BITOPS_H_
++#define _ASM_GENERIC_BITOPS_H_
++
++/*
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents. You should
++ * recode these in the native assembly language, if at all possible.
++ * To guarantee atomicity, these routines call cli() and sti() to
++ * disable interrupts while they operate. (You have to provide inline
++ * routines to cli() and sti().)
++ *
++ * Also note, these routines assume that you have 32 bit longs.
++ * You will have to change this if you are trying to port Linux to the
++ * Alpha architecture or to a Cray. :-)
++ *
++ * C language equivalents written by Theodore Ts'o, 9/26/92
++ */
++
++extern __inline__ int set_bit(int nr,long * addr)
++{
++ int mask, retval;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ cli();
++ retval = (mask & *addr) != 0;
++ *addr |= mask;
++ sti();
++ return retval;
++}
++
++extern __inline__ int clear_bit(int nr, long * addr)
++{
++ int mask, retval;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ cli();
++ retval = (mask & *addr) != 0;
++ *addr &= ~mask;
++ sti();
++ return retval;
++}
++
++extern __inline__ int test_bit(int nr, const unsigned long * addr)
++{
++ int mask;
++
++ addr += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ return ((mask & *addr) != 0);
++}
++
++/*
++ * fls: find last bit set.
++ */
++
++#define fls(x) generic_fls(x)
++
++#ifdef __KERNEL__
++
++/*
++ * ffs: find first bit set. This is defined the same way as
++ * the libc and compiler builtin ffs routines, therefore
++ * differs in spirit from the above ffz (man ffs).
++ */
++
++#define ffs(x) generic_ffs(x)
++
++/*
++ * hweightN: returns the hamming weight (i.e. the number
++ * of bits set) of a N-bit word
++ */
++
++#define hweight32(x) generic_hweight32(x)
++#define hweight16(x) generic_hweight16(x)
++#define hweight8(x) generic_hweight8(x)
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_GENERIC_BITOPS_H */
+--- linux/include/asm-generic/bug.h
++++ linux/include/asm-generic/bug.h
+@@ -0,0 +1,34 @@
++#ifndef _ASM_GENERIC_BUG_H
++#define _ASM_GENERIC_BUG_H
++
++#include <linux/compiler.h>
++// #include <linux/config.h>
++
++#ifndef HAVE_ARCH_BUG
++#define BUG() do { \
++ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
++ panic("BUG!"); \
++} while (0)
++#endif
++
++#ifndef HAVE_ARCH_PAGE_BUG
++#define PAGE_BUG(page) do { \
++ printk("page BUG for page at %p\n", page); \
++ BUG(); \
++} while (0)
++#endif
++
++#ifndef HAVE_ARCH_BUG_ON
++#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
++#endif
++
++#ifndef HAVE_ARCH_WARN_ON
++#define WARN_ON(condition) do { \
++ if (unlikely((condition)!=0)) { \
++ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
++ dump_stack(); \
++ } \
++} while (0)
++#endif
++
++#endif
+--- linux/include/asm-generic/cpumask.h
++++ linux/include/asm-generic/cpumask.h
+@@ -0,0 +1,40 @@
++#ifndef __ASM_GENERIC_CPUMASK_H
++#define __ASM_GENERIC_CPUMASK_H
++
++// #include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/types.h>
++#include <linux/bitmap.h>
++
++#if NR_CPUS > BITS_PER_LONG && NR_CPUS != 1
++#define CPU_ARRAY_SIZE BITS_TO_LONGS(NR_CPUS)
++
++struct cpumask
++{
++ unsigned long mask[CPU_ARRAY_SIZE];
++};
++
++typedef struct cpumask cpumask_t;
++
++#else
++typedef unsigned long cpumask_t;
++#endif
++
++#ifdef CONFIG_SMP
++#if NR_CPUS > BITS_PER_LONG
++#include <asm-generic/cpumask_array.h>
++#else
++#include <asm-generic/cpumask_arith.h>
++#endif
++#else
++#include <asm-generic/cpumask_up.h>
++#endif
++
++#if NR_CPUS <= 4*BITS_PER_LONG
++#include <asm-generic/cpumask_const_value.h>
++#else
++#include <asm-generic/cpumask_const_reference.h>
++#endif
++
++#endif /* __ASM_GENERIC_CPUMASK_H */
+--- linux/include/asm-generic/cpumask_arith.h
++++ linux/include/asm-generic/cpumask_arith.h
+@@ -0,0 +1,49 @@
++#ifndef __ASM_GENERIC_CPUMASK_ARITH_H
++#define __ASM_GENERIC_CPUMASK_ARITH_H
++
++/*
++ * Arithmetic type -based cpu bitmaps. A single unsigned long is used
++ * to contain the whole cpu bitmap.
++ */
++
++#define cpu_set(cpu, map) set_bit(cpu, &(map))
++#define cpu_clear(cpu, map) clear_bit(cpu, &(map))
++#define cpu_isset(cpu, map) test_bit(cpu, &(map))
++#define cpu_test_and_set(cpu, map) test_and_set_bit(cpu, &(map))
++
++#define cpus_and(dst,src1,src2) do { dst = (src1) & (src2); } while (0)
++#define cpus_or(dst,src1,src2) do { dst = (src1) | (src2); } while (0)
++#define cpus_clear(map) do { map = 0; } while (0)
++#define cpus_complement(map) do { map = ~(map); } while (0)
++#define cpus_equal(map1, map2) ((map1) == (map2))
++#define cpus_empty(map) ((map) == 0)
++#define cpus_addr(map) (&(map))
++
++#if BITS_PER_LONG == 32
++#define cpus_weight(map) hweight32(map)
++#elif BITS_PER_LONG == 64
++#define cpus_weight(map) hweight64(map)
++#endif
++
++#define cpus_shift_right(dst, src, n) do { dst = (src) >> (n); } while (0)
++#define cpus_shift_left(dst, src, n) do { dst = (src) << (n); } while (0)
++
++#define any_online_cpu(map) \
++({ \
++ cpumask_t __tmp__; \
++ cpus_and(__tmp__, map, cpu_online_map); \
++ __tmp__ ? first_cpu(__tmp__) : NR_CPUS; \
++})
++
++#define CPU_MASK_ALL (~((cpumask_t)0) >> (8*sizeof(cpumask_t) - NR_CPUS))
++#define CPU_MASK_NONE ((cpumask_t)0)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce(map) ((unsigned long)(map))
++#define cpus_promote(map) ({ map; })
++#define cpumask_of_cpu(cpu) ({ ((cpumask_t)1) << (cpu); })
++
++#define first_cpu(map) __ffs(map)
++#define next_cpu(cpu, map) find_next_bit(&(map), NR_CPUS, cpu + 1)
++
++#endif /* __ASM_GENERIC_CPUMASK_ARITH_H */
+--- linux/include/asm-generic/cpumask_array.h
++++ linux/include/asm-generic/cpumask_array.h
+@@ -0,0 +1,54 @@
++#ifndef __ASM_GENERIC_CPUMASK_ARRAY_H
++#define __ASM_GENERIC_CPUMASK_ARRAY_H
++
++/*
++ * Array-based cpu bitmaps. An array of unsigned longs is used to contain
++ * the bitmap, and then contained in a structure so it may be passed by
++ * value.
++ */
++
++#define CPU_ARRAY_SIZE BITS_TO_LONGS(NR_CPUS)
++
++#define cpu_set(cpu, map) set_bit(cpu, (map).mask)
++#define cpu_clear(cpu, map) clear_bit(cpu, (map).mask)
++#define cpu_isset(cpu, map) test_bit(cpu, (map).mask)
++#define cpu_test_and_set(cpu, map) test_and_set_bit(cpu, (map).mask)
++
++#define cpus_and(dst,src1,src2) bitmap_and((dst).mask,(src1).mask, (src2).mask, NR_CPUS)
++#define cpus_or(dst,src1,src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, NR_CPUS)
++#define cpus_clear(map) bitmap_clear((map).mask, NR_CPUS)
++#define cpus_complement(map) bitmap_complement((map).mask, NR_CPUS)
++#define cpus_equal(map1, map2) bitmap_equal((map1).mask, (map2).mask, NR_CPUS)
++#define cpus_empty(map) bitmap_empty(map.mask, NR_CPUS)
++#define cpus_addr(map) ((map).mask)
++#define cpus_weight(map) bitmap_weight((map).mask, NR_CPUS)
++#define cpus_shift_right(d, s, n) bitmap_shift_right((d).mask, (s).mask, n, NR_CPUS)
++#define cpus_shift_left(d, s, n) bitmap_shift_left((d).mask, (s).mask, n, NR_CPUS)
++#define first_cpu(map) find_first_bit((map).mask, NR_CPUS)
++#define next_cpu(cpu, map) find_next_bit((map).mask, NR_CPUS, cpu + 1)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce(map) ((map).mask[0])
++#define cpus_promote(map) ({ cpumask_t __cpu_mask = CPU_MASK_NONE;\
++ __cpu_mask.mask[0] = map; \
++ __cpu_mask; \
++ })
++#define cpumask_of_cpu(cpu) ({ cpumask_t __cpu_mask = CPU_MASK_NONE;\
++ cpu_set(cpu, __cpu_mask); \
++ __cpu_mask; \
++ })
++#define any_online_cpu(map) \
++({ \
++ cpumask_t __tmp__; \
++ cpus_and(__tmp__, map, cpu_online_map); \
++ find_first_bit(__tmp__.mask, NR_CPUS); \
++})
++
++
++/*
++ * um, these need to be usable as static initializers
++ */
++#define CPU_MASK_ALL { {[0 ... CPU_ARRAY_SIZE-1] = ~0UL} }
++#define CPU_MASK_NONE { {[0 ... CPU_ARRAY_SIZE-1] = 0UL} }
++
++#endif /* __ASM_GENERIC_CPUMASK_ARRAY_H */
+--- linux/include/asm-generic/cpumask_const_reference.h
++++ linux/include/asm-generic/cpumask_const_reference.h
+@@ -0,0 +1,29 @@
++#ifndef __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H
++#define __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H
++
++struct cpumask_ref {
++ const cpumask_t *val;
++};
++
++typedef const struct cpumask_ref cpumask_const_t;
++
++#define mk_cpumask_const(map) ((cpumask_const_t){ &(map) })
++#define cpu_isset_const(cpu, map) cpu_isset(cpu, *(map).val)
++
++#define cpus_and_const(dst,src1,src2) cpus_and(dst,*(src1).val,*(src2).val)
++#define cpus_or_const(dst,src1,src2) cpus_or(dst,*(src1).val,*(src2).val)
++
++#define cpus_equal_const(map1, map2) cpus_equal(*(map1).val, *(map2).val)
++
++#define cpus_copy_const(map1, map2) bitmap_copy((map1).mask, (map2).val->mask, NR_CPUS)
++
++#define cpus_empty_const(map) cpus_empty(*(map).val)
++#define cpus_weight_const(map) cpus_weight(*(map).val)
++#define first_cpu_const(map) first_cpu(*(map).val)
++#define next_cpu_const(cpu, map) next_cpu(cpu, *(map).val)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce_const(map) cpus_coerce(*(map).val)
++#define any_online_cpu_const(map) any_online_cpu(*(map).val)
++
++#endif /* __ASM_GENERIC_CPUMASK_CONST_REFERENCE_H */
+--- linux/include/asm-generic/cpumask_const_value.h
++++ linux/include/asm-generic/cpumask_const_value.h
+@@ -0,0 +1,21 @@
++#ifndef __ASM_GENERIC_CPUMASK_CONST_VALUE_H
++#define __ASM_GENERIC_CPUMASK_CONST_VALUE_H
++
++typedef const cpumask_t cpumask_const_t;
++
++#define mk_cpumask_const(map) (map)
++#define cpu_isset_const(cpu, map) cpu_isset(cpu, map)
++#define cpus_and_const(dst,src1,src2) cpus_and(dst, src1, src2)
++#define cpus_or_const(dst,src1,src2) cpus_or(dst, src1, src2)
++#define cpus_equal_const(map1, map2) cpus_equal(map1, map2)
++#define cpus_empty_const(map) cpus_empty(map)
++#define cpus_copy_const(map1, map2) do { map1 = (cpumask_t)map2; } while (0)
++#define cpus_weight_const(map) cpus_weight(map)
++#define first_cpu_const(map) first_cpu(map)
++#define next_cpu_const(cpu, map) next_cpu(cpu, map)
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_coerce_const(map) cpus_coerce(map)
++#define any_online_cpu_const(map) any_online_cpu(map)
++
++#endif /* __ASM_GENERIC_CPUMASK_CONST_VALUE_H */
+--- linux/include/asm-generic/cpumask_up.h
++++ linux/include/asm-generic/cpumask_up.h
+@@ -0,0 +1,59 @@
++#ifndef __ASM_GENERIC_CPUMASK_UP_H
++#define __ASM_GENERIC_CPUMASK_UP_H
++
++#define cpus_coerce(map) (map)
++
++#define cpu_set(cpu, map) do { (void)(cpu); cpus_coerce(map) = 1UL; } while (0)
++#define cpu_clear(cpu, map) do { (void)(cpu); cpus_coerce(map) = 0UL; } while (0)
++#define cpu_isset(cpu, map) ((void)(cpu), cpus_coerce(map) != 0UL)
++#define cpu_test_and_set(cpu, map) ((void)(cpu), test_and_set_bit(0, &(map)))
++
++#define cpus_and(dst, src1, src2) \
++ do { \
++ if (cpus_coerce(src1) && cpus_coerce(src2)) \
++ cpus_coerce(dst) = 1UL; \
++ else \
++ cpus_coerce(dst) = 0UL; \
++ } while (0)
++
++#define cpus_or(dst, src1, src2) \
++ do { \
++ if (cpus_coerce(src1) || cpus_coerce(src2)) \
++ cpus_coerce(dst) = 1UL; \
++ else \
++ cpus_coerce(dst) = 0UL; \
++ } while (0)
++
++#define cpus_clear(map) do { cpus_coerce(map) = 0UL; } while (0)
++
++#define cpus_complement(map) \
++ do { \
++ cpus_coerce(map) = !cpus_coerce(map); \
++ } while (0)
++
++#define cpus_equal(map1, map2) (cpus_coerce(map1) == cpus_coerce(map2))
++#define cpus_empty(map) (cpus_coerce(map) == 0UL)
++#define cpus_addr(map) (&(map))
++#define cpus_weight(map) (cpus_coerce(map) ? 1UL : 0UL)
++#define cpus_shift_right(d, s, n) do { cpus_coerce(d) = 0UL; } while (0)
++#define cpus_shift_left(d, s, n) do { cpus_coerce(d) = 0UL; } while (0)
++#define first_cpu(map) (cpus_coerce(map) ? 0 : 1)
++#define next_cpu(cpu, map) 1
++
++/* only ever use this for things that are _never_ used on large boxen */
++#define cpus_promote(map) \
++ ({ \
++ cpumask_t __tmp__; \
++ cpus_coerce(__tmp__) = map; \
++ __tmp__; \
++ })
++#define cpumask_of_cpu(cpu) ((void)(cpu), cpus_promote(1))
++#define any_online_cpu(map) (cpus_coerce(map) ? 0 : 1)
++
++/*
++ * um, these need to be usable as static initializers
++ */
++#define CPU_MASK_ALL 1UL
++#define CPU_MASK_NONE 0UL
++
++#endif /* __ASM_GENERIC_CPUMASK_UP_H */
+--- linux/include/asm-generic/div64.h
++++ linux/include/asm-generic/div64.h
+@@ -0,0 +1,58 @@
++#ifndef _ASM_GENERIC_DIV64_H
++#define _ASM_GENERIC_DIV64_H
++/*
++ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
++ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
++ *
++ * The semantics of do_div() are:
++ *
++ * uint32_t do_div(uint64_t *n, uint32_t base)
++ * {
++ * uint32_t remainder = *n % base;
++ * *n = *n / base;
++ * return remainder;
++ * }
++ *
++ * NOTE: macro parameter n is evaluated multiple times,
++ * beware of side effects!
++ */
++
++#include <linux/types.h>
++#include <linux/compiler.h>
++
++#if BITS_PER_LONG == 64
++
++# define do_div(n,base) ({ \
++ uint32_t __base = (base); \
++ uint32_t __rem; \
++ __rem = ((uint64_t)(n)) % __base; \
++ (n) = ((uint64_t)(n)) / __base; \
++ __rem; \
++ })
++
++#elif BITS_PER_LONG == 32
++
++extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
++
++/* The unnecessary pointer compare is there
++ * to check for type safety (n must be 64bit)
++ */
++# define do_div(n,base) ({ \
++ uint32_t __base = (base); \
++ uint32_t __rem; \
++ (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
++ if (likely(((n) >> 32) == 0)) { \
++ __rem = (uint32_t)(n) % __base; \
++ (n) = (uint32_t)(n) / __base; \
++ } else \
++ __rem = __div64_32(&(n), __base); \
++ __rem; \
++ })
++
++#else /* BITS_PER_LONG == ?? */
++
++# error do_div() does not yet support the C64
++
++#endif /* BITS_PER_LONG */
++
++#endif /* _ASM_GENERIC_DIV64_H */
+--- linux/include/asm-generic/dma-mapping-broken.h
++++ linux/include/asm-generic/dma-mapping-broken.h
+@@ -0,0 +1,22 @@
++#ifndef _ASM_GENERIC_DMA_MAPPING_H
++#define _ASM_GENERIC_DMA_MAPPING_H
++
++/* This is used for archs that do not support DMA */
++
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++#endif /* _ASM_GENERIC_DMA_MAPPING_H */
+--- linux/include/asm-generic/dma-mapping.h
++++ linux/include/asm-generic/dma-mapping.h
+@@ -0,0 +1,309 @@
++/* Copyright (C) 2002 by James.Bottomley@HansenPartnership.com
++ *
++ * Implements the generic device dma API via the existing pci_ one
++ * for unconverted architectures
++ */
++
++#ifndef _ASM_GENERIC_DMA_MAPPING_H
++#define _ASM_GENERIC_DMA_MAPPING_H
++
++// #include <linux/config.h>
++
++#ifdef CONFIG_PCI
++
++/* we implement the API below in terms of the existing PCI one,
++ * so include it */
++#include <linux/pci.h>
++/* need struct page definitions */
++#include <linux/mm.h>
++
++static inline int
++dma_supported(struct device *dev, u64 mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_dma_supported(to_pci_dev(dev), mask);
++}
++
++static inline int
++dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
++}
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
++}
++
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
++}
++
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
++}
++
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
++}
++
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
++}
++
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline int
++dma_mapping_error(dma_addr_t dma_addr)
++{
++ return pci_dma_mapping_error(dma_addr);
++}
++
++
++#else
++
++static inline int
++dma_supported(struct device *dev, u64 mask)
++{
++ return 0;
++}
++
++static inline int
++dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ BUG();
++ return 0;
++}
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ int flag)
++{
++ BUG();
++ return NULL;
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ BUG();
++ return 0;
++}
++
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG();
++}
++
++static inline int
++dma_error(dma_addr_t dma_addr)
++{
++ return 0;
++}
++
++#endif
++
++/* Now for the API extensions over the pci_ one */
++
++#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
++#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
++#define dma_is_consistent(d) (1)
++
++static inline int
++dma_get_cache_alignment(void)
++{
++ /* no easy way to get cache size on all processors, so return
++ * the maximum possible, to be safe */
++ return (1 << L1_CACHE_SHIFT_MAX);
++}
++
++static inline void
++dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ /* just sync everything, that's all the pci API can do */
++ dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
++}
++
++static inline void
++dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ /* just sync everything, that's all the pci API can do */
++ dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
++}
++
++static inline void
++dma_cache_sync(void *vaddr, size_t size,
++ enum dma_data_direction direction)
++{
++ /* could define this in terms of the dma_cache ... operations,
++ * but if you get this on a platform, you should convert the platform
++ * to using the generic device DMA API */
++ BUG();
++}
++
++#endif
++
+--- linux/include/asm-generic/errno-base.h
++++ linux/include/asm-generic/errno-base.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_GENERIC_ERRNO_BASE_H
++#define _ASM_GENERIC_ERRNO_BASE_H
++
++#define EPERM 1 /* Operation not permitted */
++#define ENOENT 2 /* No such file or directory */
++#define ESRCH 3 /* No such process */
++#define EINTR 4 /* Interrupted system call */
++#define EIO 5 /* I/O error */
++#define ENXIO 6 /* No such device or address */
++#define E2BIG 7 /* Argument list too long */
++#define ENOEXEC 8 /* Exec format error */
++#define EBADF 9 /* Bad file number */
++#define ECHILD 10 /* No child processes */
++#define EAGAIN 11 /* Try again */
++#define ENOMEM 12 /* Out of memory */
++#define EACCES 13 /* Permission denied */
++#define EFAULT 14 /* Bad address */
++#define ENOTBLK 15 /* Block device required */
++#define EBUSY 16 /* Device or resource busy */
++#define EEXIST 17 /* File exists */
++#define EXDEV 18 /* Cross-device link */
++#define ENODEV 19 /* No such device */
++#define ENOTDIR 20 /* Not a directory */
++#define EISDIR 21 /* Is a directory */
++#define EINVAL 22 /* Invalid argument */
++#define ENFILE 23 /* File table overflow */
++#define EMFILE 24 /* Too many open files */
++#define ENOTTY 25 /* Not a typewriter */
++#define ETXTBSY 26 /* Text file busy */
++#define EFBIG 27 /* File too large */
++#define ENOSPC 28 /* No space left on device */
++#define ESPIPE 29 /* Illegal seek */
++#define EROFS 30 /* Read-only file system */
++#define EMLINK 31 /* Too many links */
++#define EPIPE 32 /* Broken pipe */
++#define EDOM 33 /* Math argument out of domain of func */
++#define ERANGE 34 /* Math result not representable */
++
++#endif
+--- linux/include/asm-generic/errno.h
++++ linux/include/asm-generic/errno.h
+@@ -0,0 +1,100 @@
++#ifndef _ASM_GENERIC_ERRNO_H
++#define _ASM_GENERIC_ERRNO_H
++
++#include <asm-generic/errno-base.h>
++
++#define EDEADLK 35 /* Resource deadlock would occur */
++#define ENAMETOOLONG 36 /* File name too long */
++#define ENOLCK 37 /* No record locks available */
++#define ENOSYS 38 /* Function not implemented */
++#define ENOTEMPTY 39 /* Directory not empty */
++#define ELOOP 40 /* Too many symbolic links encountered */
++#define EWOULDBLOCK EAGAIN /* Operation would block */
++#define ENOMSG 42 /* No message of desired type */
++#define EIDRM 43 /* Identifier removed */
++#define ECHRNG 44 /* Channel number out of range */
++#define EL2NSYNC 45 /* Level 2 not synchronized */
++#define EL3HLT 46 /* Level 3 halted */
++#define EL3RST 47 /* Level 3 reset */
++#define ELNRNG 48 /* Link number out of range */
++#define EUNATCH 49 /* Protocol driver not attached */
++#define ENOCSI 50 /* No CSI structure available */
++#define EL2HLT 51 /* Level 2 halted */
++#define EBADE 52 /* Invalid exchange */
++#define EBADR 53 /* Invalid request descriptor */
++#define EXFULL 54 /* Exchange full */
++#define ENOANO 55 /* No anode */
++#define EBADRQC 56 /* Invalid request code */
++#define EBADSLT 57 /* Invalid slot */
++
++#define EDEADLOCK EDEADLK
++
++#define EBFONT 59 /* Bad font file format */
++#define ENOSTR 60 /* Device not a stream */
++#define ENODATA 61 /* No data available */
++#define ETIME 62 /* Timer expired */
++#define ENOSR 63 /* Out of streams resources */
++#define ENONET 64 /* Machine is not on the network */
++#define ENOPKG 65 /* Package not installed */
++#define EREMOTE 66 /* Object is remote */
++#define ENOLINK 67 /* Link has been severed */
++#define EADV 68 /* Advertise error */
++#define ESRMNT 69 /* Srmount error */
++#define ECOMM 70 /* Communication error on send */
++#define EPROTO 71 /* Protocol error */
++#define EMULTIHOP 72 /* Multihop attempted */
++#define EDOTDOT 73 /* RFS specific error */
++#define EBADMSG 74 /* Not a data message */
++#define EOVERFLOW 75 /* Value too large for defined data type */
++#define ENOTUNIQ 76 /* Name not unique on network */
++#define EBADFD 77 /* File descriptor in bad state */
++#define EREMCHG 78 /* Remote address changed */
++#define ELIBACC 79 /* Can not access a needed shared library */
++#define ELIBBAD 80 /* Accessing a corrupted shared library */
++#define ELIBSCN 81 /* .lib section in a.out corrupted */
++#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
++#define ELIBEXEC 83 /* Cannot exec a shared library directly */
++#define EILSEQ 84 /* Illegal byte sequence */
++#define ERESTART 85 /* Interrupted system call should be restarted */
++#define ESTRPIPE 86 /* Streams pipe error */
++#define EUSERS 87 /* Too many users */
++#define ENOTSOCK 88 /* Socket operation on non-socket */
++#define EDESTADDRREQ 89 /* Destination address required */
++#define EMSGSIZE 90 /* Message too long */
++#define EPROTOTYPE 91 /* Protocol wrong type for socket */
++#define ENOPROTOOPT 92 /* Protocol not available */
++#define EPROTONOSUPPORT 93 /* Protocol not supported */
++#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
++#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
++#define EPFNOSUPPORT 96 /* Protocol family not supported */
++#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
++#define EADDRINUSE 98 /* Address already in use */
++#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
++#define ENETDOWN 100 /* Network is down */
++#define ENETUNREACH 101 /* Network is unreachable */
++#define ENETRESET 102 /* Network dropped connection because of reset */
++#define ECONNABORTED 103 /* Software caused connection abort */
++#define ECONNRESET 104 /* Connection reset by peer */
++#define ENOBUFS 105 /* No buffer space available */
++#define EISCONN 106 /* Transport endpoint is already connected */
++#define ENOTCONN 107 /* Transport endpoint is not connected */
++#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
++#define ETOOMANYREFS 109 /* Too many references: cannot splice */
++#define ETIMEDOUT 110 /* Connection timed out */
++#define ECONNREFUSED 111 /* Connection refused */
++#define EHOSTDOWN 112 /* Host is down */
++#define EHOSTUNREACH 113 /* No route to host */
++#define EALREADY 114 /* Operation already in progress */
++#define EINPROGRESS 115 /* Operation now in progress */
++#define ESTALE 116 /* Stale NFS file handle */
++#define EUCLEAN 117 /* Structure needs cleaning */
++#define ENOTNAM 118 /* Not a XENIX named type file */
++#define ENAVAIL 119 /* No XENIX semaphores available */
++#define EISNAM 120 /* Is a named type file */
++#define EREMOTEIO 121 /* Remote I/O error */
++#define EDQUOT 122 /* Quota exceeded */
++
++#define ENOMEDIUM 123 /* No medium found */
++#define EMEDIUMTYPE 124 /* Wrong medium type */
++
++#endif
+--- linux/include/asm-generic/hdreg.h
++++ linux/include/asm-generic/hdreg.h
+@@ -0,0 +1,8 @@
++#warning <asm/hdreg.h> is obsolete, please do not use it
++
++#ifndef __ASM_GENERIC_HDREG_H
++#define __ASM_GENERIC_HDREG_H
++
++typedef unsigned long ide_ioreg_t;
++
++#endif /* __ASM_GENERIC_HDREG_H */
+--- linux/include/asm-generic/ide_iops.h
++++ linux/include/asm-generic/ide_iops.h
+@@ -0,0 +1,38 @@
++/* Generic I/O and MEMIO string operations. */
++
++#define __ide_insw insw
++#define __ide_insl insl
++#define __ide_outsw outsw
++#define __ide_outsl outsl
++
++static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ *(u16 *)addr = readw(port);
++ addr += 2;
++ }
++}
++
++static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ *(u32 *)addr = readl(port);
++ addr += 4;
++ }
++}
++
++static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
++{
++ while (count--) {
++ writew(*(u16 *)addr, port);
++ addr += 2;
++ }
++}
++
++static __inline__ void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
++{
++ while (count--) {
++ writel(*(u32 *)addr, port);
++ addr += 4;
++ }
++}
+--- linux/include/asm-generic/iomap.h
++++ linux/include/asm-generic/iomap.h
+@@ -0,0 +1,63 @@
++#ifndef __GENERIC_IO_H
++#define __GENERIC_IO_H
++
++#include <linux/linkage.h>
++
++/*
++ * These are the "generic" interfaces for doing new-style
++ * memory-mapped or PIO accesses. Architectures may do
++ * their own arch-optimized versions, these just act as
++ * wrappers around the old-style IO register access functions:
++ * read[bwl]/write[bwl]/in[bwl]/out[bwl]
++ *
++ * Don't include this directly, include it from <asm/io.h>.
++ */
++
++/*
++ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
++ * access or a MMIO access, these functions don't care. The info is
++ * encoded in the hardware mapping set up by the mapping functions
++ * (or the cookie itself, depending on implementation and hw).
++ *
++ * The generic routines just encode the PIO/MMIO as part of the
++ * cookie, and coldly assume that the MMIO IO mappings are not
++ * in the low address range. Architectures for which this is not
++ * true can't use this generic implementation.
++ */
++extern unsigned int fastcall ioread8(void __iomem *);
++extern unsigned int fastcall ioread16(void __iomem *);
++extern unsigned int fastcall ioread32(void __iomem *);
++
++extern void fastcall iowrite8(u8, void __iomem *);
++extern void fastcall iowrite16(u16, void __iomem *);
++extern void fastcall iowrite32(u32, void __iomem *);
++
++/*
++ * "string" versions of the above. Note that they
++ * use native byte ordering for the accesses (on
++ * the assumption that IO and memory agree on a
++ * byte order, and CPU byteorder is irrelevant).
++ *
++ * They do _not_ update the port address. If you
++ * want MMIO that copies stuff laid out in MMIO
++ * memory across multiple ports, use "memcpy_toio()"
++ * and friends.
++ */
++extern void fastcall ioread8_rep(void __iomem *port, void *buf, unsigned long count);
++extern void fastcall ioread16_rep(void __iomem *port, void *buf, unsigned long count);
++extern void fastcall ioread32_rep(void __iomem *port, void *buf, unsigned long count);
++
++extern void fastcall iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
++extern void fastcall iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
++extern void fastcall iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
++
++/* Create a virtual mapping cookie for an IO port range */
++extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
++extern void ioport_unmap(void __iomem *);
++
++/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
++struct pci_dev;
++extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
++extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
++
++#endif
+--- linux/include/asm-generic/local.h
++++ linux/include/asm-generic/local.h
+@@ -0,0 +1,118 @@
++#ifndef _ASM_GENERIC_LOCAL_H
++#define _ASM_GENERIC_LOCAL_H
++
++// #include <linux/config.h>
++#include <linux/percpu.h>
++#include <linux/hardirq.h>
++#include <asm/types.h>
++
++/* An unsigned long type for operations which are atomic for a single
++ * CPU. Usually used in combination with per-cpu variables. */
++
++#if BITS_PER_LONG == 32
++/* Implement in terms of atomics. */
++
++/* Don't use typedef: don't want them to be mixed with atomic_t's. */
++typedef struct
++{
++ atomic_t a;
++} local_t;
++
++#define LOCAL_INIT(i) { ATOMIC_INIT(i) }
++
++#define local_read(l) ((unsigned long)atomic_read(&(l)->a))
++#define local_set(l,i) atomic_set((&(l)->a),(i))
++#define local_inc(l) atomic_inc(&(l)->a)
++#define local_dec(l) atomic_dec(&(l)->a)
++#define local_add(i,l) atomic_add((i),(&(l)->a))
++#define local_sub(i,l) atomic_sub((i),(&(l)->a))
++
++/* Non-atomic variants, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well. */
++#define __local_inc(l) local_set((l), local_read(l) + 1)
++#define __local_dec(l) local_set((l), local_read(l) - 1)
++#define __local_add(i,l) local_set((l), local_read(l) + (i))
++#define __local_sub(i,l) local_set((l), local_read(l) - (i))
++
++#else /* ... can't use atomics. */
++/* Implement in terms of three variables.
++ Another option would be to use local_irq_save/restore. */
++
++typedef struct
++{
++ /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
++ unsigned long v[3];
++} local_t;
++
++#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
++
++#define LOCAL_INIT(i) { { (i), 0, 0 } }
++
++static inline unsigned long local_read(local_t *l)
++{
++ return l->v[0] + l->v[1] + l->v[2];
++}
++
++static inline void local_set(local_t *l, unsigned long v)
++{
++ l->v[0] = v;
++ l->v[1] = l->v[2] = 0;
++}
++
++static inline void local_inc(local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l)++;
++ preempt_enable();
++}
++
++static inline void local_dec(local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l)--;
++ preempt_enable();
++}
++
++static inline void local_add(unsigned long v, local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l) += v;
++ preempt_enable();
++}
++
++static inline void local_sub(unsigned long v, local_t *l)
++{
++ preempt_disable();
++ _LOCAL_VAR(l) -= v;
++ preempt_enable();
++}
++
++/* Non-atomic variants, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well. */
++#define __local_inc(l) ((l)->v[0]++)
++#define __local_dec(l) ((l)->v[0]--)
++#define __local_add(i,l) ((l)->v[0] += (i))
++#define __local_sub(i,l) ((l)->v[0] -= (i))
++
++#endif /* Non-atomic implementation */
++
++/* Use these for per-cpu local_t variables: on some archs they are
++ * much more efficient than these naive implementations. Note they take
++ * a variable (eg. mystruct.foo), not an address.
++ */
++#define cpu_local_read(v) local_read(&__get_cpu_var(v))
++#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
++#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
++#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
++#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
++#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
++
++/* Non-atomic increments, ie. preemption disabled and won't be touched
++ * in interrupt, etc. Some archs can optimize this case well.
++ */
++#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v))
++#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v))
++#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v))
++#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v))
++
++#endif /* _ASM_GENERIC_LOCAL_H */
+--- linux/include/asm-generic/pci-dma-compat.h
++++ linux/include/asm-generic/pci-dma-compat.h
+@@ -0,0 +1,107 @@
++/* include this file if the platform implements the dma_ DMA Mapping API
++ * and wants to provide the pci_ DMA Mapping API in terms of it */
++
++#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
++#define _ASM_GENERIC_PCI_DMA_COMPAT_H
++
++#include <linux/dma-mapping.h>
++
++/* note pci_set_dma_mask isn't here, since it's a public function
++ * exported from drivers/pci, use dma_supported instead */
++
++static inline int
++pci_dma_supported(struct pci_dev *hwdev, u64 mask)
++{
++ return dma_supported(hwdev == NULL ? NULL : &hwdev->dev, mask);
++}
++
++static inline void *
++pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
++ dma_addr_t *dma_handle)
++{
++ return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
++}
++
++static inline void
++pci_free_consistent(struct pci_dev *hwdev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
++}
++
++static inline dma_addr_t
++pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
++{
++ return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
++ size_t size, int direction)
++{
++ dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
++}
++
++static inline dma_addr_t
++pci_map_page(struct pci_dev *hwdev, struct page *page,
++ unsigned long offset, size_t size, int direction)
++{
++ return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
++ size_t size, int direction)
++{
++ dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
++}
++
++static inline int
++pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
++}
++
++static inline void
++pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
++}
++
++static inline int
++pci_dma_mapping_error(dma_addr_t dma_addr)
++{
++ return dma_mapping_error(dma_addr);
++}
++
++#endif
+--- linux/include/asm-generic/pci.h
++++ linux/include/asm-generic/pci.h
+@@ -0,0 +1,27 @@
++/*
++ * linux/include/asm-generic/pci.h
++ *
++ * Copyright (C) 2003 Russell King
++ */
++#ifndef _ASM_GENERIC_PCI_H
++#define _ASM_GENERIC_PCI_H
++
++/**
++ * pcibios_resource_to_bus - convert resource to PCI bus address
++ * @dev: device which owns this resource
++ * @region: converted bus-centric region (start,end)
++ * @res: resource to convert
++ *
++ * Convert a resource to a PCI device bus address or bus window.
++ */
++static inline void
++pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
++ struct resource *res)
++{
++ region->start = res->start;
++ region->end = res->end;
++}
++
++#define pcibios_scan_all_fns(a, b) 0
++
++#endif
+--- linux/include/asm-generic/percpu.h
++++ linux/include/asm-generic/percpu.h
+@@ -0,0 +1,42 @@
++#ifndef _ASM_GENERIC_PERCPU_H_
++#define _ASM_GENERIC_PERCPU_H_
++#include <linux/compiler.h>
++
++#define __GENERIC_PER_CPU
++#ifdef CONFIG_SMP
++
++extern unsigned long __per_cpu_offset[NR_CPUS];
++
++/* Separate out the type, so (int[3], foo) works. */
++#define DEFINE_PER_CPU(type, name) \
++ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
++
++/* var is in discarded region: offset to particular copy we want */
++#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
++#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
++
++/* A macro to avoid #include hell... */
++#define percpu_modcopy(pcpudst, src, size) \
++do { \
++ unsigned int __i; \
++ for (__i = 0; __i < NR_CPUS; __i++) \
++ if (cpu_possible(__i)) \
++ memcpy((pcpudst)+__per_cpu_offset[__i], \
++ (src), (size)); \
++} while (0)
++#else /* ! SMP */
++
++#define DEFINE_PER_CPU(type, name) \
++ __typeof__(type) per_cpu__##name
++
++#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
++#define __get_cpu_var(var) per_cpu__##var
++
++#endif /* SMP */
++
++#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
++
++#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
++#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
++
++#endif /* _ASM_GENERIC_PERCPU_H_ */
+--- linux/include/asm-generic/pgtable.h
++++ linux/include/asm-generic/pgtable.h
+@@ -0,0 +1,137 @@
++#ifndef _ASM_GENERIC_PGTABLE_H
++#define _ASM_GENERIC_PGTABLE_H
++
++#ifndef __HAVE_ARCH_PTEP_ESTABLISH
++/*
++ * Establish a new mapping:
++ * - flush the old one
++ * - update the page tables
++ * - inform the TLB about the new one
++ *
++ * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock.
++ *
++ * Note: the old pte is known to not be writable, so we don't need to
++ * worry about dirty bits etc getting lost.
++ */
++#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
++#define ptep_establish(__vma, __address, __ptep, __entry) \
++do { \
++ set_pte(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
++#define ptep_establish(__vma, __address, __ptep, __entry) \
++do { \
++ set_pte_atomic(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++/*
++ * Largely same as above, but only sets the access flags (dirty,
++ * accessed, and writable). Furthermore, we know it always gets set
++ * to a "more permissive" setting, which allows most architectures
++ * to optimize this.
++ */
++#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
++do { \
++ set_pte(__ptep, __entry); \
++ flush_tlb_page(__vma, __address); \
++} while (0)
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++static inline int ptep_test_and_clear_young(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ if (!pte_young(pte))
++ return 0;
++ set_pte(ptep, pte_mkold(pte));
++ return 1;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define ptep_clear_flush_young(__vma, __address, __ptep) \
++({ \
++ int __young = ptep_test_and_clear_young(__ptep); \
++ if (__young) \
++ flush_tlb_page(__vma, __address); \
++ __young; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++static inline int ptep_test_and_clear_dirty(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ if (!pte_dirty(pte))
++ return 0;
++ set_pte(ptep, pte_mkclean(pte));
++ return 1;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
++#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
++({ \
++ int __dirty = ptep_test_and_clear_dirty(__ptep); \
++ if (__dirty) \
++ flush_tlb_page(__vma, __address); \
++ __dirty; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
++static inline pte_t ptep_get_and_clear(pte_t *ptep)
++{
++ pte_t pte = *ptep;
++ pte_clear(ptep);
++ return pte;
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
++#define ptep_clear_flush(__vma, __address, __ptep) \
++({ \
++ pte_t __pte = ptep_get_and_clear(__ptep); \
++ flush_tlb_page(__vma, __address); \
++ __pte; \
++})
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
++static inline void ptep_set_wrprotect(pte_t *ptep)
++{
++ pte_t old_pte = *ptep;
++ set_pte(ptep, pte_wrprotect(old_pte));
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTEP_MKDIRTY
++static inline void ptep_mkdirty(pte_t *ptep)
++{
++ pte_t old_pte = *ptep;
++ set_pte(ptep, pte_mkdirty(old_pte));
++}
++#endif
++
++#ifndef __HAVE_ARCH_PTE_SAME
++#define pte_same(A,B) (pte_val(A) == pte_val(B))
++#endif
++
++#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
++#define page_test_and_clear_dirty(page) (0)
++#endif
++
++#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
++#define page_test_and_clear_young(page) (0)
++#endif
++
++#ifndef __HAVE_ARCH_PGD_OFFSET_GATE
++#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr)
++#endif
++
++#endif /* _ASM_GENERIC_PGTABLE_H */
+--- linux/include/asm-generic/rmap.h
++++ linux/include/asm-generic/rmap.h
+@@ -0,0 +1,90 @@
++#ifndef _GENERIC_RMAP_H
++#define _GENERIC_RMAP_H
++/*
++ * linux/include/asm-generic/rmap.h
++ *
++ * Architecture dependent parts of the reverse mapping code,
++ * this version should work for most architectures with a
++ * 'normal' page table layout.
++ *
++ * We use the struct page of the page table page to find out
++ * the process and full address of a page table entry:
++ * - page->mapping points to the process' mm_struct
++ * - page->index has the high bits of the address
++ * - the lower bits of the address are calculated from the
++ * offset of the page table entry within the page table page
++ *
++ * For CONFIG_HIGHPTE, we need to represent the address of a pte in a
++ * scalar pte_addr_t. The pfn of the pte's page is shifted left by PAGE_SIZE
++ * bits and is then ORed with the byte offset of the pte within its page.
++ *
++ * For CONFIG_HIGHMEM4G, the pte_addr_t is 32 bits. 20 for the pfn, 12 for
++ * the offset.
++ *
++ * For CONFIG_HIGHMEM64G, the pte_addr_t is 64 bits. 52 for the pfn, 12 for
++ * the offset.
++ */
++#include <linux/mm.h>
++
++static inline void pgtable_add_rmap(struct page * page, struct mm_struct * mm, unsigned long address)
++{
++#ifdef BROKEN_PPC_PTE_ALLOC_ONE
++ /* OK, so PPC calls pte_alloc() before mem_map[] is setup ... ;( */
++ extern int mem_init_done;
++
++ if (!mem_init_done)
++ return;
++#endif
++ page->mapping = (void *)mm;
++ page->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1);
++ inc_page_state(nr_page_table_pages);
++}
++
++static inline void pgtable_remove_rmap(struct page * page)
++{
++ page->mapping = NULL;
++ page->index = 0;
++ dec_page_state(nr_page_table_pages);
++}
++
++static inline struct mm_struct * ptep_to_mm(pte_t * ptep)
++{
++ struct page * page = kmap_atomic_to_page(ptep);
++ return (struct mm_struct *) page->mapping;
++}
++
++static inline unsigned long ptep_to_address(pte_t * ptep)
++{
++ struct page * page = kmap_atomic_to_page(ptep);
++ unsigned long low_bits;
++ low_bits = ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
++ return page->index + low_bits;
++}
++
++#ifdef CONFIG_HIGHPTE
++static inline pte_addr_t ptep_to_paddr(pte_t *ptep)
++{
++ pte_addr_t paddr;
++ paddr = ((pte_addr_t)page_to_pfn(kmap_atomic_to_page(ptep))) << PAGE_SHIFT;
++ return paddr + (pte_addr_t)((unsigned long)ptep & ~PAGE_MASK);
++}
++#else
++static inline pte_addr_t ptep_to_paddr(pte_t *ptep)
++{
++ return (pte_addr_t)ptep;
++}
++#endif
++
++#ifndef CONFIG_HIGHPTE
++static inline pte_t *rmap_ptep_map(pte_addr_t pte_paddr)
++{
++ return (pte_t *)pte_paddr;
++}
++
++static inline void rmap_ptep_unmap(pte_t *pte)
++{
++ return;
++}
++#endif
++
++#endif /* _GENERIC_RMAP_H */
+--- linux/include/asm-generic/rtc.h
++++ linux/include/asm-generic/rtc.h
+@@ -0,0 +1,213 @@
++/*
++ * inclue/asm-generic/rtc.h
++ *
++ * Author: Tom Rini <trini@mvista.com>
++ *
++ * Based on:
++ * drivers/char/rtc.c
++ *
++ * Please read the COPYING file for all license details.
++ */
++
++#ifndef __ASM_RTC_H__
++#define __ASM_RTC_H__
++
++#ifdef __KERNEL__
++
++#include <linux/mc146818rtc.h>
++#include <linux/rtc.h>
++#include <linux/bcd.h>
++
++#define RTC_PIE 0x40 /* periodic interrupt enable */
++#define RTC_AIE 0x20 /* alarm interrupt enable */
++#define RTC_UIE 0x10 /* update-finished interrupt enable */
++
++/* some dummy definitions */
++#define RTC_BATT_BAD 0x100 /* battery bad */
++#define RTC_SQWE 0x08 /* enable square-wave output */
++#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
++#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
++#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
++
++/*
++ * Returns true if a clock update is in progress
++ */
++static inline unsigned char rtc_is_updating(void)
++{
++ unsigned char uip;
++
++ spin_lock_irq(&rtc_lock);
++ uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
++ spin_unlock_irq(&rtc_lock);
++ return uip;
++}
++
++static inline unsigned int get_rtc_time(struct rtc_time *time)
++{
++ unsigned long uip_watchdog = jiffies;
++ unsigned char ctrl;
++#ifdef CONFIG_MACH_DECSTATION
++ unsigned int real_year;
++#endif
++
++ /*
++ * read RTC once any update in progress is done. The update
++ * can take just over 2ms. We wait 10 to 20ms. There is no need to
++ * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
++ * If you need to know *exactly* when a second has started, enable
++ * periodic update complete interrupts, (via ioctl) and then
++ * immediately read /dev/rtc which will block until you get the IRQ.
++ * Once the read clears, read the RTC time (again via ioctl). Easy.
++ */
++
++ if (rtc_is_updating() != 0)
++ while (jiffies - uip_watchdog < 2*HZ/100) {
++ barrier();
++ cpu_relax();
++ }
++
++ /*
++ * Only the values that we read from the RTC are set. We leave
++ * tm_wday, tm_yday and tm_isdst untouched. Even though the
++ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
++ * by the RTC when initially set to a non-zero value.
++ */
++ spin_lock_irq(&rtc_lock);
++ time->tm_sec = CMOS_READ(RTC_SECONDS);
++ time->tm_min = CMOS_READ(RTC_MINUTES);
++ time->tm_hour = CMOS_READ(RTC_HOURS);
++ time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
++ time->tm_mon = CMOS_READ(RTC_MONTH);
++ time->tm_year = CMOS_READ(RTC_YEAR);
++#ifdef CONFIG_MACH_DECSTATION
++ real_year = CMOS_READ(RTC_DEC_YEAR);
++#endif
++ ctrl = CMOS_READ(RTC_CONTROL);
++ spin_unlock_irq(&rtc_lock);
++
++ if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
++ {
++ BCD_TO_BIN(time->tm_sec);
++ BCD_TO_BIN(time->tm_min);
++ BCD_TO_BIN(time->tm_hour);
++ BCD_TO_BIN(time->tm_mday);
++ BCD_TO_BIN(time->tm_mon);
++ BCD_TO_BIN(time->tm_year);
++ }
++
++#ifdef CONFIG_MACH_DECSTATION
++ time->tm_year += real_year - 72;
++#endif
++
++ /*
++ * Account for differences between how the RTC uses the values
++ * and how they are defined in a struct rtc_time;
++ */
++ if (time->tm_year <= 69)
++ time->tm_year += 100;
++
++ time->tm_mon--;
++
++ return RTC_24H;
++}
++
++/* Set the current date and time in the real time clock. */
++static inline int set_rtc_time(struct rtc_time *time)
++{
++ unsigned char mon, day, hrs, min, sec;
++ unsigned char save_control, save_freq_select;
++ unsigned int yrs;
++#ifdef CONFIG_MACH_DECSTATION
++ unsigned int real_yrs, leap_yr;
++#endif
++
++ yrs = time->tm_year;
++ mon = time->tm_mon + 1; /* tm_mon starts at zero */
++ day = time->tm_mday;
++ hrs = time->tm_hour;
++ min = time->tm_min;
++ sec = time->tm_sec;
++
++ if (yrs > 255) /* They are unsigned */
++ return -EINVAL;
++
++ spin_lock_irq(&rtc_lock);
++#ifdef CONFIG_MACH_DECSTATION
++ real_yrs = yrs;
++ leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
++ !((yrs + 1900) % 400));
++ yrs = 72;
++
++ /*
++ * We want to keep the year set to 73 until March
++ * for non-leap years, so that Feb, 29th is handled
++ * correctly.
++ */
++ if (!leap_yr && mon < 3) {
++ real_yrs--;
++ yrs = 73;
++ }
++#endif
++ /* These limits and adjustments are independent of
++ * whether the chip is in binary mode or not.
++ */
++ if (yrs > 169) {
++ spin_unlock_irq(&rtc_lock);
++ return -EINVAL;
++ }
++
++ if (yrs >= 100)
++ yrs -= 100;
++
++ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
++ || RTC_ALWAYS_BCD) {
++ BIN_TO_BCD(sec);
++ BIN_TO_BCD(min);
++ BIN_TO_BCD(hrs);
++ BIN_TO_BCD(day);
++ BIN_TO_BCD(mon);
++ BIN_TO_BCD(yrs);
++ }
++
++ save_control = CMOS_READ(RTC_CONTROL);
++ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
++ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
++ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
++
++#ifdef CONFIG_MACH_DECSTATION
++ CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
++#endif
++ CMOS_WRITE(yrs, RTC_YEAR);
++ CMOS_WRITE(mon, RTC_MONTH);
++ CMOS_WRITE(day, RTC_DAY_OF_MONTH);
++ CMOS_WRITE(hrs, RTC_HOURS);
++ CMOS_WRITE(min, RTC_MINUTES);
++ CMOS_WRITE(sec, RTC_SECONDS);
++
++ CMOS_WRITE(save_control, RTC_CONTROL);
++ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
++
++ spin_unlock_irq(&rtc_lock);
++
++ return 0;
++}
++
++static inline unsigned int get_rtc_ss(void)
++{
++ struct rtc_time h;
++
++ get_rtc_time(&h);
++ return h.tm_sec;
++}
++
++static inline int get_rtc_pll(struct rtc_pll_info *pll)
++{
++ return -EINVAL;
++}
++static inline int set_rtc_pll(struct rtc_pll_info *pll)
++{
++ return -EINVAL;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __ASM_RTC_H__ */
+--- linux/include/asm-generic/sections.h
++++ linux/include/asm-generic/sections.h
+@@ -0,0 +1,12 @@
++#ifndef _ASM_GENERIC_SECTIONS_H_
++#define _ASM_GENERIC_SECTIONS_H_
++
++/* References to section boundaries */
++
++extern char _text[], _stext[], _etext[];
++extern char _data[], _sdata[], _edata[];
++extern char __bss_start[], __bss_stop[];
++extern char __init_begin[], __init_end[];
++extern char _sinittext[], _einittext[];
++
++#endif /* _ASM_GENERIC_SECTIONS_H_ */
+--- linux/include/asm-generic/siginfo.h
++++ linux/include/asm-generic/siginfo.h
+@@ -0,0 +1,295 @@
++#ifndef _ASM_GENERIC_SIGINFO_H
++#define _ASM_GENERIC_SIGINFO_H
++
++#include <linux/compiler.h>
++#include <linux/types.h>
++#include <linux/resource.h>
++
++typedef union sigval {
++ int sival_int;
++ void __user *sival_ptr;
++} sigval_t;
++
++/*
++ * This is the size (including padding) of the part of the
++ * struct siginfo that is before the union.
++ */
++#ifndef __ARCH_SI_PREAMBLE_SIZE
++#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
++#endif
++
++#define SI_MAX_SIZE 128
++#ifndef SI_PAD_SIZE
++#define SI_PAD_SIZE ((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
++#endif
++
++#ifndef __ARCH_SI_UID_T
++#define __ARCH_SI_UID_T uid_t
++#endif
++
++/*
++ * The default "si_band" type is "long", as specified by POSIX.
++ * However, some architectures want to override this to "int"
++ * for historical compatibility reasons, so we allow that.
++ */
++#ifndef __ARCH_SI_BAND_T
++#define __ARCH_SI_BAND_T long
++#endif
++
++#ifndef HAVE_ARCH_SIGINFO_T
++
++typedef struct siginfo {
++ int si_signo;
++ int si_errno;
++ int si_code;
++
++ union {
++ int _pad[SI_PAD_SIZE];
++
++ /* kill() */
++ struct {
++ pid_t _pid; /* sender's pid */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ } _kill;
++
++ /* POSIX.1b timers */
++ struct {
++ timer_t _tid; /* timer id */
++ int _overrun; /* overrun count */
++ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
++ sigval_t _sigval; /* same as below */
++ int _sys_private; /* not to be passed to user */
++ } _timer;
++
++ /* POSIX.1b signals */
++ struct {
++ pid_t _pid; /* sender's pid */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ sigval_t _sigval;
++ } _rt;
++
++ /* SIGCHLD */
++ struct {
++ pid_t _pid; /* which child */
++ __ARCH_SI_UID_T _uid; /* sender's uid */
++ int _status; /* exit code */
++ clock_t _utime;
++ clock_t _stime;
++ } _sigchld;
++
++ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
++ struct {
++ void __user *_addr; /* faulting insn/memory ref. */
++#ifdef __ARCH_SI_TRAPNO
++ int _trapno; /* TRAP # which caused the signal */
++#endif
++ } _sigfault;
++
++ /* SIGPOLL */
++ struct {
++ __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
++ int _fd;
++ } _sigpoll;
++ } _sifields;
++} siginfo_t;
++
++#endif
++
++/*
++ * How these fields are to be accessed.
++ */
++#define si_pid _sifields._kill._pid
++#define si_uid _sifields._kill._uid
++#define si_tid _sifields._timer._tid
++#define si_overrun _sifields._timer._overrun
++#define si_sys_private _sifields._timer._sys_private
++#define si_status _sifields._sigchld._status
++#define si_utime _sifields._sigchld._utime
++#define si_stime _sifields._sigchld._stime
++#define si_value _sifields._rt._sigval
++#define si_int _sifields._rt._sigval.sival_int
++#define si_ptr _sifields._rt._sigval.sival_ptr
++#define si_addr _sifields._sigfault._addr
++#ifdef __ARCH_SI_TRAPNO
++#define si_trapno _sifields._sigfault._trapno
++#endif
++#define si_band _sifields._sigpoll._band
++#define si_fd _sifields._sigpoll._fd
++
++#ifdef __KERNEL__
++#define __SI_MASK 0xffff0000u
++#define __SI_KILL (0 << 16)
++#define __SI_TIMER (1 << 16)
++#define __SI_POLL (2 << 16)
++#define __SI_FAULT (3 << 16)
++#define __SI_CHLD (4 << 16)
++#define __SI_RT (5 << 16)
++#define __SI_MESGQ (6 << 16)
++#define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
++#else
++#define __SI_KILL 0
++#define __SI_TIMER 0
++#define __SI_POLL 0
++#define __SI_FAULT 0
++#define __SI_CHLD 0
++#define __SI_RT 0
++#define __SI_MESGQ 0
++#define __SI_CODE(T,N) (N)
++#endif
++
++/*
++ * si_code values
++ * Digital reserves positive values for kernel-generated signals.
++ */
++#define SI_USER 0 /* sent by kill, sigsend, raise */
++#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
++#define SI_QUEUE -1 /* sent by sigqueue */
++#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
++#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change */
++#define SI_ASYNCIO -4 /* sent by AIO completion */
++#define SI_SIGIO -5 /* sent by queued SIGIO */
++#define SI_TKILL -6 /* sent by tkill system call */
++#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
++
++#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
++#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
++
++#ifndef HAVE_ARCH_SI_CODES
++/*
++ * SIGILL si_codes
++ */
++#define ILL_ILLOPC (__SI_FAULT|1) /* illegal opcode */
++#define ILL_ILLOPN (__SI_FAULT|2) /* illegal operand */
++#define ILL_ILLADR (__SI_FAULT|3) /* illegal addressing mode */
++#define ILL_ILLTRP (__SI_FAULT|4) /* illegal trap */
++#define ILL_PRVOPC (__SI_FAULT|5) /* privileged opcode */
++#define ILL_PRVREG (__SI_FAULT|6) /* privileged register */
++#define ILL_COPROC (__SI_FAULT|7) /* coprocessor error */
++#define ILL_BADSTK (__SI_FAULT|8) /* internal stack error */
++#define NSIGILL 8
++
++/*
++ * SIGFPE si_codes
++ */
++#define FPE_INTDIV (__SI_FAULT|1) /* integer divide by zero */
++#define FPE_INTOVF (__SI_FAULT|2) /* integer overflow */
++#define FPE_FLTDIV (__SI_FAULT|3) /* floating point divide by zero */
++#define FPE_FLTOVF (__SI_FAULT|4) /* floating point overflow */
++#define FPE_FLTUND (__SI_FAULT|5) /* floating point underflow */
++#define FPE_FLTRES (__SI_FAULT|6) /* floating point inexact result */
++#define FPE_FLTINV (__SI_FAULT|7) /* floating point invalid operation */
++#define FPE_FLTSUB (__SI_FAULT|8) /* subscript out of range */
++#define NSIGFPE 8
++
++/*
++ * SIGSEGV si_codes
++ */
++#define SEGV_MAPERR (__SI_FAULT|1) /* address not mapped to object */
++#define SEGV_ACCERR (__SI_FAULT|2) /* invalid permissions for mapped object */
++#define NSIGSEGV 2
++
++/*
++ * SIGBUS si_codes
++ */
++#define BUS_ADRALN (__SI_FAULT|1) /* invalid address alignment */
++#define BUS_ADRERR (__SI_FAULT|2) /* non-existant physical address */
++#define BUS_OBJERR (__SI_FAULT|3) /* object specific hardware error */
++#define NSIGBUS 3
++
++/*
++ * SIGTRAP si_codes
++ */
++#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */
++#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
++#define NSIGTRAP 2
++
++/*
++ * SIGCHLD si_codes
++ */
++#define CLD_EXITED (__SI_CHLD|1) /* child has exited */
++#define CLD_KILLED (__SI_CHLD|2) /* child was killed */
++#define CLD_DUMPED (__SI_CHLD|3) /* child terminated abnormally */
++#define CLD_TRAPPED (__SI_CHLD|4) /* traced child has trapped */
++#define CLD_STOPPED (__SI_CHLD|5) /* child has stopped */
++#define CLD_CONTINUED (__SI_CHLD|6) /* stopped child has continued */
++#define NSIGCHLD 6
++
++/*
++ * SIGPOLL si_codes
++ */
++#define POLL_IN (__SI_POLL|1) /* data input available */
++#define POLL_OUT (__SI_POLL|2) /* output buffers available */
++#define POLL_MSG (__SI_POLL|3) /* input message available */
++#define POLL_ERR (__SI_POLL|4) /* i/o error */
++#define POLL_PRI (__SI_POLL|5) /* high priority input available */
++#define POLL_HUP (__SI_POLL|6) /* device disconnected */
++#define NSIGPOLL 6
++
++#endif
++
++/*
++ * sigevent definitions
++ *
++ * It seems likely that SIGEV_THREAD will have to be handled from
++ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
++ * thread manager then catches and does the appropriate nonsense.
++ * However, everything is written out here so as to not get lost.
++ */
++#define SIGEV_SIGNAL 0 /* notify via signal */
++#define SIGEV_NONE 1 /* other notification: meaningless */
++#define SIGEV_THREAD 2 /* deliver via thread creation */
++#define SIGEV_THREAD_ID 4 /* deliver to thread */
++
++#define SIGEV_MAX_SIZE 64
++#ifndef SIGEV_PAD_SIZE
++#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
++#endif
++
++#ifndef HAVE_ARCH_SIGEVENT_T
++
++typedef struct sigevent {
++ sigval_t sigev_value;
++ int sigev_signo;
++ int sigev_notify;
++ union {
++ int _pad[SIGEV_PAD_SIZE];
++ int _tid;
++
++ struct {
++ void (*_function)(sigval_t);
++ void *_attribute; /* really pthread_attr_t */
++ } _sigev_thread;
++ } _sigev_un;
++} sigevent_t;
++
++#endif
++
++#define sigev_notify_function _sigev_un._sigev_thread._function
++#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
++#define sigev_notify_thread_id _sigev_un._tid
++
++#ifdef __KERNEL__
++
++struct siginfo;
++void do_schedule_next_timer(struct siginfo *info);
++
++#ifndef HAVE_ARCH_COPY_SIGINFO
++
++#include <linux/string.h>
++
++static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
++{
++ if (from->si_code < 0)
++ memcpy(to, from, sizeof(*to));
++ else
++ /* _sigchld is currently the largest know union member */
++ memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
++}
++
++#endif
++
++extern int copy_siginfo_to_user(struct siginfo __user *to, struct siginfo *from);
++
++#endif /* __KERNEL__ */
++
++#endif
+--- linux/include/asm-generic/statfs.h
++++ linux/include/asm-generic/statfs.h
+@@ -0,0 +1,51 @@
++#ifndef _GENERIC_STATFS_H
++#define _GENERIC_STATFS_H
++
++#ifndef __KERNEL_STRICT_NAMES
++# include <linux/types.h>
++typedef __kernel_fsid_t fsid_t;
++#endif
++
++struct statfs {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u32 f_blocks;
++ __u32 f_bfree;
++ __u32 f_bavail;
++ __u32 f_files;
++ __u32 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++struct statfs64 {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u64 f_blocks;
++ __u64 f_bfree;
++ __u64 f_bavail;
++ __u64 f_files;
++ __u64 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++struct compat_statfs64 {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u64 f_blocks;
++ __u64 f_bfree;
++ __u64 f_bavail;
++ __u64 f_files;
++ __u64 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++
++#endif
+--- linux/include/asm-generic/tlb.h
++++ linux/include/asm-generic/tlb.h
+@@ -0,0 +1,152 @@
++/* asm-generic/tlb.h
++ *
++ * Generic TLB shootdown code
++ *
++ * Copyright 2001 Red Hat, Inc.
++ * Based on code from mm/memory.c Copyright Linus Torvalds and others.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#ifndef _ASM_GENERIC__TLB_H
++#define _ASM_GENERIC__TLB_H
++
++// #include <linux/config.h>
++#include <linux/swap.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++
++/*
++ * For UP we don't need to worry about TLB flush
++ * and page free order so much..
++ */
++#ifdef CONFIG_SMP
++ #define FREE_PTE_NR 506
++ #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
++#else
++ #define FREE_PTE_NR 1
++ #define tlb_fast_mode(tlb) 1
++#endif
++
++/* struct mmu_gather is an opaque type used by the mm code for passing around
++ * any data needed by arch specific code for tlb_remove_page. This structure
++ * can be per-CPU or per-MM as the page table lock is held for the duration of
++ * TLB shootdown.
++ */
++struct mmu_gather {
++ struct mm_struct *mm;
++ unsigned int nr; /* set to ~0U means fast mode */
++ unsigned int need_flush;/* Really unmapped some ptes? */
++ unsigned int fullmm; /* non-zero means full mm flush */
++ unsigned long freed;
++ struct page * pages[FREE_PTE_NR];
++};
++
++/* Users of the generic TLB shootdown code must declare this storage space. */
++DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++/* tlb_gather_mmu
++ * Return a pointer to an initialized struct mmu_gather.
++ */
++static inline struct mmu_gather *
++tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
++{
++ struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id());
++
++ tlb->mm = mm;
++
++ /* Use fast mode if only one CPU is online */
++ tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
++
++ tlb->fullmm = full_mm_flush;
++ tlb->freed = 0;
++
++ return tlb;
++}
++
++static inline void
++tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++ if (!tlb->need_flush)
++ return;
++ tlb->need_flush = 0;
++ tlb_flush(tlb);
++ if (!tlb_fast_mode(tlb)) {
++ free_pages_and_swap_cache(tlb->pages, tlb->nr);
++ tlb->nr = 0;
++ }
++}
++
++/* tlb_finish_mmu
++ * Called at the end of the shootdown operation to free up any resources
++ * that were required. The page table lock is still held at this point.
++ */
++static inline void
++tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++ int freed = tlb->freed;
++ struct mm_struct *mm = tlb->mm;
++ int rss = mm->rss;
++
++ if (rss < freed)
++ freed = rss;
++ mm->rss = rss - freed;
++ tlb_flush_mmu(tlb, start, end);
++
++ /* keep the page table cache within bounds */
++ check_pgt_cache();
++}
++
++static inline unsigned int
++tlb_is_full_mm(struct mmu_gather *tlb)
++{
++ return tlb->fullmm;
++}
++
++/* tlb_remove_page
++ * Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while
++ * handling the additional races in SMP caused by other CPUs caching valid
++ * mappings in their TLBs.
++ */
++static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
++{
++ tlb->need_flush = 1;
++ if (tlb_fast_mode(tlb)) {
++ free_page_and_swap_cache(page);
++ return;
++ }
++ tlb->pages[tlb->nr++] = page;
++ if (tlb->nr >= FREE_PTE_NR)
++ tlb_flush_mmu(tlb, 0, 0);
++}
++
++/**
++ * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
++ *
++ * Record the fact that pte's were really umapped in ->need_flush, so we can
++ * later optimise away the tlb invalidate. This helps when userspace is
++ * unmapping already-unmapped pages, which happens quite a lot.
++ */
++#define tlb_remove_tlb_entry(tlb, ptep, address) \
++ do { \
++ tlb->need_flush = 1; \
++ __tlb_remove_tlb_entry(tlb, ptep, address); \
++ } while (0)
++
++#define pte_free_tlb(tlb, ptep) \
++ do { \
++ tlb->need_flush = 1; \
++ __pte_free_tlb(tlb, ptep); \
++ } while (0)
++
++#define pmd_free_tlb(tlb, pmdp) \
++ do { \
++ tlb->need_flush = 1; \
++ __pmd_free_tlb(tlb, pmdp); \
++ } while (0)
++
++#define tlb_migrate_finish(mm) do {} while (0)
++
++#endif /* _ASM_GENERIC__TLB_H */
+--- linux/include/asm-generic/topology.h
++++ linux/include/asm-generic/topology.h
+@@ -0,0 +1,53 @@
++/*
++ * linux/include/asm-generic/topology.h
++ *
++ * Written by: Matthew Dobson, IBM Corporation
++ *
++ * Copyright (C) 2002, IBM Corp.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ * Send feedback to <colpatch@us.ibm.com>
++ */
++#ifndef _ASM_GENERIC_TOPOLOGY_H
++#define _ASM_GENERIC_TOPOLOGY_H
++
++/* Other architectures wishing to use this simple topology API should fill
++ in the below functions as appropriate in their own <asm/topology.h> file. */
++#ifndef cpu_to_node
++#define cpu_to_node(cpu) (0)
++#endif
++#ifndef parent_node
++#define parent_node(node) (0)
++#endif
++#ifndef node_to_cpumask
++#define node_to_cpumask(node) (cpu_online_map)
++#endif
++#ifndef node_to_first_cpu
++#define node_to_first_cpu(node) (0)
++#endif
++#ifndef pcibus_to_cpumask
++#define pcibus_to_cpumask(bus) (cpu_online_map)
++#endif
++
++/* Cross-node load balancing interval. */
++#ifndef NODE_BALANCE_RATE
++#define NODE_BALANCE_RATE 10
++#endif
++
++#endif /* _ASM_GENERIC_TOPOLOGY_H */
+--- linux/include/asm-generic/uaccess.h
++++ linux/include/asm-generic/uaccess.h
+@@ -0,0 +1,26 @@
++#ifndef _ASM_GENERIC_UACCESS_H_
++#define _ASM_GENERIC_UACCESS_H_
++
++/*
++ * This macro should be used instead of __get_user() when accessing
++ * values at locations that are not known to be aligned.
++ */
++#define __get_user_unaligned(x, ptr) \
++({ \
++ __typeof__ (*(ptr)) __x; \
++ __copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0; \
++ (x) = __x; \
++})
++
++
++/*
++ * This macro should be used instead of __put_user() when accessing
++ * values at locations that are not known to be aligned.
++ */
++#define __put_user_unaligned(x, ptr) \
++({ \
++ __typeof__ (*(ptr)) __x = (x); \
++ __copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0; \
++})
++
++#endif /* _ASM_GENERIC_UACCESS_H */
+--- linux/include/asm-generic/unaligned.h
++++ linux/include/asm-generic/unaligned.h
+@@ -0,0 +1,20 @@
++#ifndef _ASM_GENERIC_UNALIGNED_H_
++#define _ASM_GENERIC_UNALIGNED_H_
++
++/*
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents.
++ */
++
++#include <asm/string.h>
++
++
++#define get_unaligned(ptr) \
++ ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
++
++#define put_unaligned(val, ptr) \
++ ({ __typeof__(*(ptr)) __tmp = (val); \
++ memcpy((ptr), &__tmp, sizeof(*(ptr))); \
++ (void)0; })
++
++#endif /* _ASM_GENERIC_UNALIGNED_H */
+--- linux/include/asm-generic/vmlinux.lds.h
++++ linux/include/asm-generic/vmlinux.lds.h
+@@ -0,0 +1,84 @@
++#ifndef LOAD_OFFSET
++#define LOAD_OFFSET 0
++#endif
++
++#ifndef VMLINUX_SYMBOL
++#define VMLINUX_SYMBOL(_sym_) _sym_
++#endif
++
++#define RODATA \
++ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
++ *(.rodata) *(.rodata.*) \
++ *(__vermagic) /* Kernel version magic */ \
++ } \
++ \
++ .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
++ *(.rodata1) \
++ } \
++ \
++ /* PCI quirks */ \
++ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
++ *(.pci_fixup_header) \
++ VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
++ VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
++ *(.pci_fixup_final) \
++ VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
++ } \
++ \
++ /* Kernel symbol table: Normal symbols */ \
++ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___ksymtab) = .; \
++ *(__ksymtab) \
++ VMLINUX_SYMBOL(__stop___ksymtab) = .; \
++ } \
++ \
++ /* Kernel symbol table: GPL-only symbols */ \
++ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
++ *(__ksymtab_gpl) \
++ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
++ } \
++ \
++ /* Kernel symbol table: Normal symbols */ \
++ __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___kcrctab) = .; \
++ *(__kcrctab) \
++ VMLINUX_SYMBOL(__stop___kcrctab) = .; \
++ } \
++ \
++ /* Kernel symbol table: GPL-only symbols */ \
++ __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
++ *(__kcrctab_gpl) \
++ VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
++ } \
++ \
++ /* Kernel symbol table: strings */ \
++ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
++ *(__ksymtab_strings) \
++ } \
++ \
++ /* Built-in module parameters. */ \
++ __param : AT(ADDR(__param) - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__start___param) = .; \
++ *(__param) \
++ VMLINUX_SYMBOL(__stop___param) = .; \
++ }
++
++#define SECURITY_INIT \
++ .security_initcall.init : { \
++ VMLINUX_SYMBOL(__security_initcall_start) = .; \
++ *(.security_initcall.init) \
++ VMLINUX_SYMBOL(__security_initcall_end) = .; \
++ }
++
++#define SCHED_TEXT \
++ VMLINUX_SYMBOL(__sched_text_start) = .; \
++ *(.sched.text) \
++ VMLINUX_SYMBOL(__sched_text_end) = .;
++
++#define LOCK_TEXT \
++ VMLINUX_SYMBOL(__lock_text_start) = .; \
++ *(.spinlock.text) \
++ VMLINUX_SYMBOL(__lock_text_end) = .;
+--- linux/include/asm-generic/xor.h
++++ linux/include/asm-generic/xor.h
+@@ -0,0 +1,718 @@
++/*
++ * include/asm-generic/xor.h
++ *
++ * Generic optimized RAID-5 checksumming functions.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * You should have received a copy of the GNU General Public License
++ * (for example /usr/src/linux/COPYING); if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <asm/processor.h>
++
++static void
++xor_8regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0];
++ p1[1] ^= p2[1];
++ p1[2] ^= p2[2];
++ p1[3] ^= p2[3];
++ p1[4] ^= p2[4];
++ p1[5] ^= p2[5];
++ p1[6] ^= p2[6];
++ p1[7] ^= p2[7];
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0];
++ p1[1] ^= p2[1] ^ p3[1];
++ p1[2] ^= p2[2] ^ p3[2];
++ p1[3] ^= p2[3] ^ p3[3];
++ p1[4] ^= p2[4] ^ p3[4];
++ p1[5] ^= p2[5] ^ p3[5];
++ p1[6] ^= p2[6] ^ p3[6];
++ p1[7] ^= p2[7] ^ p3[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0] ^ p5[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1] ^ p5[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2] ^ p5[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3] ^ p5[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4] ^ p5[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5] ^ p5[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6] ^ p5[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7] ^ p5[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_32regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8;
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ d0 ^= p5[0];
++ d1 ^= p5[1];
++ d2 ^= p5[2];
++ d3 ^= p5[3];
++ d4 ^= p5[4];
++ d5 ^= p5[5];
++ d6 ^= p5[6];
++ d7 ^= p5[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++}
++
++static void
++xor_8regs_p_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++ prefetchw(p1);
++ prefetch(p2);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ once_more:
++ p1[0] ^= p2[0];
++ p1[1] ^= p2[1];
++ p1[2] ^= p2[2];
++ p1[3] ^= p2[3];
++ p1[4] ^= p2[4];
++ p1[5] ^= p2[5];
++ p1[6] ^= p2[6];
++ p1[7] ^= p2[7];
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0];
++ p1[1] ^= p2[1] ^ p3[1];
++ p1[2] ^= p2[2] ^ p3[2];
++ p1[3] ^= p2[3] ^ p3[3];
++ p1[4] ^= p2[4] ^ p3[4];
++ p1[5] ^= p2[5] ^ p3[5];
++ p1[6] ^= p2[6] ^ p3[6];
++ p1[7] ^= p2[7] ^ p3[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_8regs_p_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++ prefetch(p5);
++
++ do {
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ prefetch(p5+8);
++ once_more:
++ p1[0] ^= p2[0] ^ p3[0] ^ p4[0] ^ p5[0];
++ p1[1] ^= p2[1] ^ p3[1] ^ p4[1] ^ p5[1];
++ p1[2] ^= p2[2] ^ p3[2] ^ p4[2] ^ p5[2];
++ p1[3] ^= p2[3] ^ p3[3] ^ p4[3] ^ p5[3];
++ p1[4] ^= p2[4] ^ p3[4] ^ p4[4] ^ p5[4];
++ p1[5] ^= p2[5] ^ p3[5] ^ p4[5] ^ p5[5];
++ p1[6] ^= p2[6] ^ p3[6] ^ p4[6] ^ p5[6];
++ p1[7] ^= p2[7] ^ p3[7] ^ p4[7] ^ p5[7];
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static void
++xor_32regs_p_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ long lines = bytes / (sizeof (long)) / 8 - 1;
++
++ prefetchw(p1);
++ prefetch(p2);
++ prefetch(p3);
++ prefetch(p4);
++ prefetch(p5);
++
++ do {
++ register long d0, d1, d2, d3, d4, d5, d6, d7;
++
++ prefetchw(p1+8);
++ prefetch(p2+8);
++ prefetch(p3+8);
++ prefetch(p4+8);
++ prefetch(p5+8);
++ once_more:
++ d0 = p1[0]; /* Pull the stuff into registers */
++ d1 = p1[1]; /* ... in bursts, if possible. */
++ d2 = p1[2];
++ d3 = p1[3];
++ d4 = p1[4];
++ d5 = p1[5];
++ d6 = p1[6];
++ d7 = p1[7];
++ d0 ^= p2[0];
++ d1 ^= p2[1];
++ d2 ^= p2[2];
++ d3 ^= p2[3];
++ d4 ^= p2[4];
++ d5 ^= p2[5];
++ d6 ^= p2[6];
++ d7 ^= p2[7];
++ d0 ^= p3[0];
++ d1 ^= p3[1];
++ d2 ^= p3[2];
++ d3 ^= p3[3];
++ d4 ^= p3[4];
++ d5 ^= p3[5];
++ d6 ^= p3[6];
++ d7 ^= p3[7];
++ d0 ^= p4[0];
++ d1 ^= p4[1];
++ d2 ^= p4[2];
++ d3 ^= p4[3];
++ d4 ^= p4[4];
++ d5 ^= p4[5];
++ d6 ^= p4[6];
++ d7 ^= p4[7];
++ d0 ^= p5[0];
++ d1 ^= p5[1];
++ d2 ^= p5[2];
++ d3 ^= p5[3];
++ d4 ^= p5[4];
++ d5 ^= p5[5];
++ d6 ^= p5[6];
++ d7 ^= p5[7];
++ p1[0] = d0; /* Store the result (in bursts) */
++ p1[1] = d1;
++ p1[2] = d2;
++ p1[3] = d3;
++ p1[4] = d4;
++ p1[5] = d5;
++ p1[6] = d6;
++ p1[7] = d7;
++ p1 += 8;
++ p2 += 8;
++ p3 += 8;
++ p4 += 8;
++ p5 += 8;
++ } while (--lines > 0);
++ if (lines == 0)
++ goto once_more;
++}
++
++static struct xor_block_template xor_block_8regs = {
++ .name = "8regs",
++ .do_2 = xor_8regs_2,
++ .do_3 = xor_8regs_3,
++ .do_4 = xor_8regs_4,
++ .do_5 = xor_8regs_5,
++};
++
++static struct xor_block_template xor_block_32regs = {
++ .name = "32regs",
++ .do_2 = xor_32regs_2,
++ .do_3 = xor_32regs_3,
++ .do_4 = xor_32regs_4,
++ .do_5 = xor_32regs_5,
++};
++
++static struct xor_block_template xor_block_8regs_p = {
++ .name = "8regs_prefetch",
++ .do_2 = xor_8regs_p_2,
++ .do_3 = xor_8regs_p_3,
++ .do_4 = xor_8regs_p_4,
++ .do_5 = xor_8regs_p_5,
++};
++
++static struct xor_block_template xor_block_32regs_p = {
++ .name = "32regs_prefetch",
++ .do_2 = xor_32regs_p_2,
++ .do_3 = xor_32regs_p_3,
++ .do_4 = xor_32regs_p_4,
++ .do_5 = xor_32regs_p_5,
++};
++
++#define XOR_TRY_TEMPLATES \
++ do { \
++ xor_speed(&xor_block_8regs); \
++ xor_speed(&xor_block_8regs_p); \
++ xor_speed(&xor_block_32regs); \
++ xor_speed(&xor_block_32regs_p); \
++ } while (0)
+--- linux/include/asm-nios2nommu/ChangeLog
++++ linux/include/asm-nios2nommu/ChangeLog
+@@ -0,0 +1,14 @@
++2004-06-29 Ken Hill <khill@microtronix.com>
++
++ * bitops.h (find_next_zero_bit): Fix problem with with masking for found_first
++ handling. The masking of the upper bits for size < 32 bits would set all
++ the bits to 1. Removing any zero's there may have been.
++
++2004-06-02 Ken Hill <khill@microtronix.com>
++
++ * processor.h (TASK_SIZE): Change na_sdram_end to nasys_program_mem_end to remove
++ dependancy on quartus memory component name.
++
++ * page.h (PAGE_OFFSET): Change na_sdram to nasys_program_mem to remove
++ dependancy on quartus memory component name.
++
+--- linux/include/asm-nios2nommu/a.out.h
++++ linux/include/asm-nios2nommu/a.out.h
+@@ -0,0 +1,85 @@
++/* $Id: a.out.h,v 1.4 2004/03/30 19:35:04 ken-h Exp $ */
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_A_OUT_H__
++#define __NIOS2NOMMU_A_OUT_H__
++
++#define SPARC_PGSIZE 0x1000 /* Thanks to the sun4 architecture... */
++#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
++
++struct exec {
++ unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
++ unsigned char a_toolversion:7;
++ unsigned char a_machtype;
++ unsigned short a_info;
++ unsigned long a_text; /* length of text, in bytes */
++ unsigned long a_data; /* length of data, in bytes */
++ unsigned long a_bss; /* length of bss, in bytes */
++ unsigned long a_syms; /* length of symbol table, in bytes */
++ unsigned long a_entry; /* where program begins */
++ unsigned long a_trsize;
++ unsigned long a_drsize;
++};
++
++#define INIT_EXEC { \
++ .a_dynamic = 0, \
++ .a_toolversion = 0, \
++ .a_machtype = 0, \
++ .a_info = 0, \
++ .a_text = 0, \
++ .a_data = 0, \
++ .a_bss = 0, \
++ .a_syms = 0, \
++ .a_entry = 0, \
++ .a_trsize = 0, \
++ .a_drsize = 0, \
++}
++
++/* Where in the file does the text information begin? */
++#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
++
++/* Where do the Symbols start? */
++#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
++ (x).a_data + (x).a_trsize + \
++ (x).a_drsize)
++
++/* Where does text segment go in memory after being loaded? */
++#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \
++ ((x).a_entry < SPARC_PGSIZE)) ? \
++ 0 : SPARC_PGSIZE)
++
++/* And same for the data segment.. */
++#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
++ (N_TXTADDR(x) + (x).a_text) \
++ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
++
++#define N_TRSIZE(a) ((a).a_trsize)
++#define N_DRSIZE(a) ((a).a_drsize)
++#define N_SYMSIZE(a) ((a).a_syms)
++
++#ifdef __KERNEL__
++
++#define STACK_TOP TASK_SIZE
++
++#endif
++
++#endif /* __NIOS2NOMMU_A_OUT_H__ */
+--- linux/include/asm-nios2nommu/asm-macros.h
++++ linux/include/asm-nios2nommu/asm-macros.h
+@@ -0,0 +1,331 @@
++/*
++ * Macro used to simplify coding multi-line assembler.
++ * Some of the bit test macro can simplify down to one line
++ * depending on the mask value.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++/*
++ * ANDs reg2 with mask and places the result in reg1.
++ *
++ * You cannnot use the same register for reg1 & reg2.
++ */
++
++.macro ANDI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ movhi \reg1,%hi(\mask)
++ movui \reg1,%lo(\mask)
++ and \reg1,\reg1,\reg2
++ .else
++ andi \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ andhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * ORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro ORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ orhi \reg1,\reg2,%hi(\mask)
++ ori \reg1,\reg2,%lo(\mask)
++ .else
++ ori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ orhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * XORs reg2 with mask and places the result in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro XORI32 reg1,reg2,mask
++ .if \mask & 0xffff
++ .if \mask & 0xffff0000
++ xorhi \reg1,\reg2,%hi(\mask)
++ xori \reg1,\reg1,%lo(\mask)
++ .else
++ xori \reg1,\reg2,%lo(\mask)
++ .endif
++ .else
++ xorhi \reg1,\reg2,%hi(\mask)
++ .endif
++.endm
++
++/*
++ * This is a support macro for BTBZ & BTBNZ. It checks
++ * the bit to make sure it is valid 32 value.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BT reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and branches to label if the
++ * bit is non-zero. The result of the bit test is stored in reg1.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTBNZ reg1,reg2,bit,label
++ BT \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTC reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ xori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ xorhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTS reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ ori \reg2,\reg2,(1 << \bit)
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ orhi \reg2,\reg2,(1 << (\bit - 16))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTR reg1,reg2,bit
++.if \bit > 31
++ .err
++.else
++ .if \bit < 16
++ andi \reg1,\reg2,(1 << \bit)
++ andi \reg2,\reg2,%lo(~(1 << \bit))
++ .else
++ andhi \reg1,\reg2,(1 << (\bit - 16))
++ andhi \reg2,\reg2,%lo(~(1 << (\bit - 16)))
++ .endif
++.endif
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then compliments the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTCBNZ reg1,reg2,bit,label
++ BTC \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then sets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTSBNZ reg1,reg2,bit,label
++ BTS \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bit in reg2 and then resets the bit in reg2.
++ * The result of the bit test is stored in reg1. If the
++ * original bit was non-zero it branches to label.
++ *
++ * It is NOT safe to use the same register for reg1 & reg2.
++ */
++
++.macro BTRBNZ reg1,reg2,bit,label
++ BTR \reg1,\reg2,\bit
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the all the bits in the mask are zero it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ beq \reg1,r0,\label
++.endm
++
++/*
++ * Tests the bits in mask against reg2 stores the result in reg1.
++ * If the any of the bits in the mask are 1 it branches to label.
++ *
++ * It is safe to use the same register for reg1 & reg2.
++ */
++
++.macro TSTBNZ reg1,reg2,mask,label
++ ANDI32 \reg1,\reg2,\mask
++ bne \reg1,r0,\label
++.endm
++
++/*
++ * Pushes reg onto the stack.
++ */
++
++.macro PUSH reg
++ addi sp,sp,-4
++ stw \reg,0(sp)
++.endm
++
++/*
++ * Pops the top of the stack into reg.
++ */
++
++.macro POP reg
++ ldw \reg,0(sp)
++ addi sp,sp,4
++.endm
++
++/*
++ * Clears reg
++ */
++
++.macro CLR reg
++ mov \reg,r0
++.endm
++
++/*
++ * The preprocessor macro does not work for
++ * the nios2 compiler. Undefine ENTRY and define
++ * a real assembler macro.
++ */
++#undef ENTRY
++#define ENTRY(name) ASM_ENTRY name
++
++.macro ASM_ENTRY name
++.globl \name
++__ALIGN
++ \name:
++.endm
+--- linux/include/asm-nios2nommu/atomic.h
++++ linux/include/asm-nios2nommu/atomic.h
+@@ -0,0 +1,190 @@
++//vic - add 'atomic_add/sub_return', 'atomic_add_negative'
++//vic from v850 architecture
++
++/* atomic.h:
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2001 Vic Phillips (vic@microtronix.com)
++ *
++ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2NOMMU_ATOMIC__
++#define __ARCH_NIOS2NOMMU_ATOMIC__
++
++#include <asm/system.h>
++
++typedef struct { int counter; } atomic_t;
++#define ATOMIC_INIT(i) { (i) }
++
++#define atomic_read(v) ((v)->counter)
++#define atomic_set(v, i) (((v)->counter) = i)
++
++
++extern __inline__ void atomic_add(int i, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter += i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_add_negative(int i, atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++
++ local_irq_save(flags);
++ v->counter += i;
++ result = (v->counter < 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_sub(int i, atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++{
++ int result;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_inc(atomic_t *v)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter += 1;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_inc_and_test(atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++
++ local_irq_save(flags);
++ v->counter += 1;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ void atomic_dec(atomic_t *v)
++{
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ local_irq_restore(flags);
++}
++
++extern __inline__ int atomic_dec_and_test(atomic_t *v)
++{
++ int result;
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = (v->counter == 0);
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_inc_return(atomic_t *v)
++{
++ int result;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ result = ++v->counter;
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_dec_return(atomic_t *v)
++{
++ int result;
++ int i = 1; /* the compiler optimizes better this way */
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v->counter -= i;
++ result = v->counter;
++ local_irq_restore(flags);
++ return result;
++}
++
++extern __inline__ int atomic_add_return (int i, volatile atomic_t *v)
++{
++ int res;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ res = v->counter + i;
++ v->counter = res;
++ local_irq_restore(flags);
++
++ return res;
++}
++
++static __inline__ int atomic_sub_return (int i, volatile atomic_t *v)
++{
++ int res;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ res = v->counter - i;
++ v->counter = res;
++ local_irq_restore(flags);
++
++ return res;
++}
++
++#define atomic_dec_return(v) atomic_sub_return(1,(v))
++#define atomic_inc_return(v) atomic_add_return(1,(v))
++
++/* Atomic operations are already serializing */
++#define smp_mb__before_atomic_dec() barrier()
++#define smp_mb__after_atomic_dec() barrier()
++#define smp_mb__before_atomic_inc() barrier()
++#define smp_mb__after_atomic_inc() barrier()
++
++
++#endif /* !(__ARCH_NIOS2NOMMU_ATOMIC__) */
++
++
+--- linux/include/asm-nios2nommu/bitops.h
++++ linux/include/asm-nios2nommu/bitops.h
+@@ -0,0 +1,472 @@
++#ifndef _ASM_NIOS_BITOPS_H_
++#define _ASM_NIOS_BITOPS_H_
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bitops.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef __KERNEL__
++#include <linux/config.h>
++#include <linux/compiler.h>
++#include <asm/byteorder.h> /* swab32 */
++#include <asm/system.h>
++#endif
++
++/*
++ * Adapted to NIOS from generic bitops.h:
++ *
++ * For the benefit of those who are trying to port Linux to another
++ * architecture, here are some C-language equivalents. You should
++ * recode these in the native assembly language, if at all possible.
++ * To guarantee atomicity, these routines call cli() and sti() to
++ * disable interrupts while they operate. (You have to provide inline
++ * routines to cli() and sti().)
++ *
++ * Also note, these routines assume that you have 32 bit integers.
++ * You will have to change this if you are trying to port Linux to the
++ * Alpha architecture or to a Cray. :-)
++ *
++ * C language equivalents written by Theodore Ts'o, 9/26/92
++ */
++
++/*
++ * Generic ffs().
++ */
++static inline int ffs(int x)
++{
++ int r = 1;
++
++ if (!x)
++ return 0;
++ if (!(x & 0xffff)) {
++ x >>= 16;
++ r += 16;
++ }
++ if (!(x & 0xff)) {
++ x >>= 8;
++ r += 8;
++ }
++ if (!(x & 0xf)) {
++ x >>= 4;
++ r += 4;
++ }
++ if (!(x & 3)) {
++ x >>= 2;
++ r += 2;
++ }
++ if (!(x & 1)) {
++ x >>= 1;
++ r += 1;
++ }
++ return r;
++}
++
++/*
++ * Generic __ffs().
++ */
++static inline int __ffs(int x)
++{
++ int r = 0;
++
++ if (!x)
++ return 0;
++ if (!(x & 0xffff)) {
++ x >>= 16;
++ r += 16;
++ }
++ if (!(x & 0xff)) {
++ x >>= 8;
++ r += 8;
++ }
++ if (!(x & 0xf)) {
++ x >>= 4;
++ r += 4;
++ }
++ if (!(x & 3)) {
++ x >>= 2;
++ r += 2;
++ }
++ if (!(x & 1)) {
++ x >>= 1;
++ r += 1;
++ }
++ return r;
++}
++
++/*
++ * fls: find last bit set.
++ */
++#define fls(x) generic_fls(x)
++
++
++/*
++ * Every architecture must define this function. It's the fastest
++ * way of searching a 140-bit bitmap where the first 100 bits are
++ * unlikely to be set. It's guaranteed that at least one of the 140
++ * bits is cleared.
++ */
++static inline int sched_find_first_bit(unsigned long *b)
++{
++ if (unlikely(b[0]))
++ return __ffs(b[0]);
++ if (unlikely(b[1]))
++ return __ffs(b[1]) + 32;
++ if (unlikely(b[2]))
++ return __ffs(b[2]) + 64;
++ if (b[3])
++ return __ffs(b[3]) + 96;
++ return __ffs(b[4]) + 128;
++}
++
++/*
++ * ffz = Find First Zero in word. Undefined if no zero exists,
++ * so code should check against ~0UL first..
++ */
++static __inline__ unsigned long ffz(unsigned long word)
++{
++ unsigned long result = 0;
++
++ while(word & 1) {
++ result++;
++ word >>= 1;
++ }
++ return result;
++}
++
++
++static __inline__ void set_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ *a |= mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ *a |= mask;
++}
++
++/*
++ * clear_bit() doesn't provide any barrier for the compiler.
++ */
++#define smp_mb__before_clear_bit() barrier()
++#define smp_mb__after_clear_bit() barrier()
++
++static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ *a &= ~mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __clear_bit(int nr, volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ *a &= ~mask;
++}
++
++static __inline__ void change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, flags;
++ unsigned long *ADDR = (unsigned long *) addr;
++
++ ADDR += nr >> 5;
++ mask = 1 << (nr & 31);
++ local_irq_save(flags);
++ *ADDR ^= mask;
++ local_irq_restore(flags);
++}
++
++static __inline__ void __change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask;
++ unsigned long *ADDR = (unsigned long *) addr;
++
++ ADDR += nr >> 5;
++ mask = 1 << (nr & 31);
++ *ADDR ^= mask;
++}
++
++static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a |= mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a |= mask;
++ return retval;
++}
++
++static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a &= ~mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a &= ~mask;
++ return retval;
++}
++
++static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++ unsigned long flags;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ local_irq_save(flags);
++ retval = (mask & *a) != 0;
++ *a ^= mask;
++ local_irq_restore(flags);
++
++ return retval;
++}
++
++static __inline__ int __test_and_change_bit(int nr, volatile unsigned long * addr)
++{
++ int mask, retval;
++ volatile unsigned int *a = (volatile unsigned int *) addr;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ retval = (mask & *a) != 0;
++ *a ^= mask;
++ return retval;
++}
++
++/*
++ * This routine doesn't need to be atomic.
++ */
++static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr)
++{
++ return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
++}
++
++static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
++{
++ int * a = (int *) addr;
++ int mask;
++
++ a += nr >> 5;
++ mask = 1 << (nr & 0x1f);
++ return ((mask & *a) != 0);
++}
++
++#define test_bit(nr,addr) \
++(__builtin_constant_p(nr) ? \
++ __constant_test_bit((nr),(unsigned long *)(addr)) : \
++ __test_bit((nr),(unsigned long *)(addr)))
++
++
++/* find_next_zero_bit() finds the first zero bit in a bit string of length
++ * 'size' bits, starting the search at bit 'offset'. This is largely based
++ * on Linus's ALPHA routines, which are pretty portable BTW.
++ */
++
++extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
++{
++ unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
++ unsigned long result = offset & ~31UL;
++ unsigned long tmp;
++
++ if (offset >= size)
++ return size;
++ size -= result;
++ offset &= 31UL;
++ if (offset) {
++ tmp = *(p++);
++ tmp |= ~0UL >> (32-offset);
++ if (size < 32)
++ goto found_first;
++ if (~tmp)
++ goto found_middle;
++ size -= 32;
++ result += 32;
++ }
++ while (size & ~31UL) {
++ if (~(tmp = *(p++)))
++ goto found_middle;
++ result += 32;
++ size -= 32;
++ }
++ if (!size)
++ return result;
++ tmp = *p;
++
++found_first:
++ tmp |= ~0UL << size;
++ if (tmp == ~0UL)
++ return result + size;
++found_middle:
++ return result + ffz(tmp);
++}
++
++/*
++ * Find next one bit in a bitmap reasonably efficiently.
++ */
++extern __inline__ unsigned long find_next_bit(const unsigned long *addr,
++ unsigned long size, unsigned long offset)
++{
++ unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
++ unsigned int result = offset & ~31UL;
++ unsigned int tmp;
++
++ if (offset >= size)
++ return size;
++ size -= result;
++ offset &= 31UL;
++ if (offset) {
++ tmp = *p++;
++ tmp &= ~0UL << offset;
++ if (size < 32)
++ goto found_first;
++ if (tmp)
++ goto found_middle;
++ size -= 32;
++ result += 32;
++ }
++ while (size >= 32) {
++ if ((tmp = *p++) != 0)
++ goto found_middle;
++ result += 32;
++ size -= 32;
++ }
++ if (!size)
++ return result;
++ tmp = *p;
++
++found_first:
++ tmp &= ~0UL >> (32 - size);
++ if (tmp == 0UL) /* Are any bits set? */
++ return result + size; /* Nope. */
++found_middle:
++ return result + __ffs(tmp);
++}
++
++/*
++ * hweightN: returns the hamming weight (i.e. the number
++ * of bits set) of a N-bit word
++ */
++
++#define hweight32(x) generic_hweight32(x)
++#define hweight16(x) generic_hweight16(x)
++#define hweight8(x) generic_hweight8(x)
++
++/* Linus sez that gcc can optimize the following correctly, we'll see if this
++ * holds on the Sparc as it does for the ALPHA.
++ */
++
++#define find_first_zero_bit(addr, size) \
++ find_next_zero_bit((addr), (size), 0)
++#define find_first_bit(addr, size) \
++ find_next_bit((addr), (size), 0)
++
++/* Now for the ext2 filesystem bit operations and helper routines.
++ *
++ * Both NIOS and ext2 are little endian, so these are the same as above.
++ */
++
++#define ext2_set_bit test_and_set_bit
++#define ext2_clear_bit test_and_clear_bit
++#define ext2_test_bit test_bit
++
++#define ext2_set_bit_atomic(lock, nr, addr) \
++ ({ \
++ int ret; \
++ spin_lock(lock); \
++ ret = ext2_set_bit((nr),(unsigned long *) (addr)); \
++ spin_unlock(lock); \
++ ret; \
++ })
++
++#define ext2_clear_bit_atomic(lock, nr, addr) \
++ ({ \
++ int ret; \
++ spin_lock(lock); \
++ ret = ext2_clear_bit((nr),(unsigned long *) (addr)); \
++ spin_unlock(lock); \
++ ret; \
++ })
++
++#define ext2_find_first_zero_bit find_first_zero_bit
++#define ext2_find_next_zero_bit find_next_zero_bit
++
++#endif /* _ASM_NIOS_BITOPS_H */
+--- linux/include/asm-nios2nommu/bootinfo.h
++++ linux/include/asm-nios2nommu/bootinfo.h
+@@ -0,0 +1,2 @@
++
++/* Nothing for nios2nommu */
+--- linux/include/asm-nios2nommu/bug.h
++++ linux/include/asm-nios2nommu/bug.h
+@@ -0,0 +1,48 @@
++#ifndef _NIOS2NOMMU_BUG_H
++#define _NIOS2NOMMU_BUG_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bug.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define BUG() do { \
++ printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
++} while (0)
++
++#define BUG_ON(condition) do { \
++ if (unlikely((condition)!=0)) \
++ BUG(); \
++} while(0)
++
++#define PAGE_BUG(page) do { \
++ BUG(); \
++} while (0)
++
++#define WARN_ON(condition) do { \
++ if (unlikely((condition)!=0)) { \
++ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
++ dump_stack(); \
++ } \
++} while (0)
++
++#endif
+--- linux/include/asm-nios2nommu/bugs.h
++++ linux/include/asm-nios2nommu/bugs.h
+@@ -0,0 +1,40 @@
++#ifndef __ASM_NIOS_BUGS_H
++#define __ASM_NIOS_BUGS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/bugs.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1994 Linus Torvalds
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This is included by init/main.c to check for architecture-dependent bugs.
++ *
++ * Needs:
++ * void check_bugs(void);
++ */
++
++static void check_bugs(void)
++{
++}
++
++#endif
+--- linux/include/asm-nios2nommu/byteorder.h
++++ linux/include/asm-nios2nommu/byteorder.h
+@@ -0,0 +1,38 @@
++#ifndef __ASM_NIOS_BYTEORDER_H
++#define __ASM_NIOS_BYTEORDER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/byteorder.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/types.h>
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
++# define __BYTEORDER_HAS_U64__
++# define __SWAB_64_THRU_32__
++#endif
++
++#include <linux/byteorder/little_endian.h>
++
++#endif
++
+--- linux/include/asm-nios2nommu/cache.h
++++ linux/include/asm-nios2nommu/cache.h
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2NOMMU_CACHE_H
++#define __ARCH_NIOS2NOMMU_CACHE_H
++
++#include <asm/nios.h>
++
++/* bytes per L1 cache line */
++#define L1_CACHE_BYTES nasys_icache_line_size /* this need to be at least 1 */
++
++
++#define __cacheline_aligned
++#define ____cacheline_aligned
++
++#endif
+--- linux/include/asm-nios2nommu/cachectl.h
++++ linux/include/asm-nios2nommu/cachectl.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_CACHECTL_H
++#define _NIOS2NOMMU_CACHECTL_H
++
++/* Definitions for the cacheflush system call. */
++
++#define FLUSH_SCOPE_LINE 1 /* Flush a cache line */
++#define FLUSH_SCOPE_PAGE 2 /* Flush a page */
++#define FLUSH_SCOPE_ALL 3 /* Flush the whole cache -- superuser only */
++
++#define FLUSH_CACHE_DATA 1 /* Writeback and flush data cache */
++#define FLUSH_CACHE_INSN 2 /* Flush instruction cache */
++#define FLUSH_CACHE_BOTH 3 /* Flush both caches */
++
++#endif /* _NIOS2NOMMU_CACHECTL_H */
+--- linux/include/asm-nios2nommu/cacheflush.h
++++ linux/include/asm-nios2nommu/cacheflush.h
+@@ -0,0 +1,56 @@
++#ifndef _NIOS2NOMMU_CACHEFLUSH_H
++#define _NIOS2NOMMU_CACHEFLUSH_H
++
++/*
++ * Ported from m68knommu.
++ *
++ * (C) Copyright 2003, Microtronix Datacom Ltd.
++ * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/mm.h>
++
++extern void cache_push (unsigned long vaddr, int len);
++extern void dcache_push (unsigned long vaddr, int len);
++extern void icache_push (unsigned long vaddr, int len);
++extern void cache_push_all (void);
++
++#define flush_cache_all() __flush_cache_all()
++#define flush_cache_mm(mm) do { } while (0)
++#define flush_cache_range(vma, start, end) do { } while (0)
++#define flush_cache_page(vma, vmaddr) do { } while (0)
++#define flush_dcache_range(start,end) dcache_push(start, end - start)
++#define flush_dcache_page(page) do { } while (0)
++#define flush_icache_range(start,end) cache_push(start, end - start)
++#define flush_icache_page(vma,pg) do { } while (0)
++#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
++
++extern inline void __flush_cache_all(void)
++{
++ cache_push_all();
++}
++
++#endif /* _NIOS2NOMMU_CACHEFLUSH_H */
+--- linux/include/asm-nios2nommu/checksum.h
++++ linux/include/asm-nios2nommu/checksum.h
+@@ -0,0 +1,320 @@
++#ifndef __NIOS2_CHECKSUM_H
++#define __NIOS2_CHECKSUM_H
++
++/* checksum.h: IP/UDP/TCP checksum routines on the NIOS.
++ *
++ * Copyright(C) 1995 Linus Torvalds
++ * Copyright(C) 1995 Miguel de Icaza
++ * Copyright(C) 1996 David S. Miller
++ * Copyright(C) 2001 Ken Hill
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * derived from:
++ * Alpha checksum c-code
++ * ix86 inline assembly
++ * Spar nommu
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++
++extern inline unsigned short csum_tcpudp_magic(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++" add %0, %3, %0\n"
++" bgeu %0, %3, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %4, %0\n"
++" bgeu %0, %4, 1f\n"
++" addi %0, %0, 1\n"
++"1: add %0, %5, %0\n"
++" bgeu %0, %5, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++/*
++ We need the carry from the addition of 16-bit
++ significant addition, so we zap out the low bits
++ in one half, zap out the high bits in another,
++ shift them both up to the top 16-bits of a word
++ and do the carry producing addition, finally
++ shift the result back down to the low 16-bits.
++
++ Actually, we can further optimize away two shifts
++ because we know the low bits of the original
++ value will be added to zero-only bits so cannot
++ affect the addition result nor the final carry
++ bit.
++*/
++" slli %1,%0, 16\n" /* Need a copy to fold with */
++ /* Bring the LOW 16 bits up */
++" add %0, %1, %0\n" /* add and set carry, neat eh? */
++" cmpltu r15, %0, %1\n" /* get remaining carry bit */
++" srli %0, %0, 16\n" /* shift back down the result */
++" add %0, %0, r15\n"
++" nor %0, %0, %0\n" /* negate */
++ : "=&r" (sum), "=&r" (saddr)
++ : "0" (sum), "1" (saddr), "r" (ntohl(len+proto)), "r" (daddr)
++ : "r15");
++ return ((unsigned short) sum);
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++ extern inline unsigned short from32to16(unsigned long x)
++ {
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r15, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r15\n"
++ : "=r" (x)
++ : "r" (x << 16), "0" (x)
++ : "r15");
++ return x;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern inline unsigned long do_csum(const unsigned char * buff, int len)
++{
++ int odd, count;
++ unsigned long result = 0;
++
++ barrier();
++ if (len <= 0)
++ goto out;
++ odd = 1 & (unsigned long) buff;
++ if (odd) {
++////result = *buff; // dgt: Big endian
++ result = *buff << 8; // dgt: Little endian
++
++ len--;
++ buff++;
++ }
++ count = len >> 1; /* nr of 16-bit words.. */
++ if (count) {
++ if (2 & (unsigned long) buff) {
++ result += *(unsigned short *) buff;
++ count--;
++ len -= 2;
++ buff += 2;
++ }
++ count >>= 1; /* nr of 32-bit words.. */
++ if (count) {
++ unsigned long carry = 0;
++ do {
++ unsigned long w = *(unsigned long *) buff;
++ count--;
++ buff += 4;
++ result += carry;
++ result += w;
++ carry = (w > result);
++ } while (count);
++ result += carry;
++ result = (result & 0xffff) + (result >> 16);
++ }
++ if (len & 2) {
++ result += *(unsigned short *) buff;
++ buff += 2;
++ }
++ }
++ if (len & 1)
++ result += *buff; /* This is little machine, byte is right */
++ result = from32to16(result);
++ if (odd)
++ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
++out:
++ return result;
++ barrier();
++ }
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/* ihl is always 5 or greater, almost always is 5, iph is always word
++ * aligned but can fail to be dword aligned very often.
++ */
++
++ extern inline unsigned short ip_fast_csum(const unsigned char *iph, unsigned int ihl)
++ {
++ unsigned int sum;
++
++ barrier();
++ __asm__ __volatile__(
++" andi r8, %1, 2\n" /* Remember original alignment */
++" ldw %0, (%1)\n" /* 16 or 32 bit boundary */
++" beq r8, r0, 1f\n" /* Aligned on 32 bit boundary, go */
++" srli %0, %0, 16\n" /* Get correct 16 bits */
++" addi %2, %2, -1\n" /* Take off for 4 bytes, pickup last 2 at end */
++" addi %1, %1, 2\n" /* Adjust pointer to 32 bit boundary */
++" br 2f\n"
++"1:\n"
++" addi %2, %2, -1\n"
++" addi %1, %1, 4\n" /* Bump ptr a long word */
++"2:\n"
++" ldw r9, (%1)\n"
++"1:\n"
++" add %0, r9, %0\n"
++" bgeu %0, r9, 2f\n"
++" addi %0, %0, 1\n"
++"2:\n"
++" addi %1, %1, 4\n"
++" addi %2, %2, -1\n"
++" ldw r9, (%1)\n"
++" bne %2, r0, 1b\n"
++" beq r8, r0, 1f\n" /* 32 bit boundary time to leave */
++" srli r9, r9, 16\n" /* 16 bit boundary, get correct 16 bits */
++" add %0, r9, %0\n"
++" bgeu %0, r9, 1f\n"
++" addi %0, %0, 1\n"
++"1:\n"
++" slli %2, %0, 16\n"
++" add %0, %2, %0\n"
++" cmpltu r8, %0, %2\n"
++" srli %0, %0, 16\n"
++" add %0, %0, r8\n"
++" nor %0, %0, %0\n"
++ : "=&r" (sum), "=&r" (iph), "=&r" (ihl)
++ : "1" (iph), "2" (ihl)
++ : "r8", "r9");
++ return sum;
++ barrier();
++ }
++
++/*these 2 functions are now in checksum.c */
++unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
++unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++/*
++ * the same as csum_partial_copy, but copies from user space.
++ *
++ * here even more important to align src and dst on a 32-bit (or even
++ * better 64-bit) boundary
++ */
++extern inline unsigned int
++csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
++{
++ barrier();
++ if (csum_err) *csum_err = 0;
++ memcpy(dst, src, len);
++ return csum_partial(dst, len, sum);
++ barrier();
++}
++
++#define csum_partial_copy_nocheck(src, dst, len, sum) \
++ csum_partial_copy ((src), (dst), (len), (sum))
++
++
++/*
++ * this routine is used for miscellaneous IP-like checksums, mainly
++ * in icmp.c
++ */
++
++extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
++{
++ barrier();
++ return ~from32to16(do_csum(buff,len));
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++#define csum_partial_copy_fromuser(s, d, l, w) \
++ csum_partial_copy((char *) (s), (d), (l), (w))
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++/*
++ * Fold a partial checksum without adding pseudo headers
++ */
++extern __inline__ unsigned int csum_fold(unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "srli %0, %0, 16\n"
++ "add %0, %0, r8\n"
++ "nor %0, %0, %0\n"
++ : "=r" (sum)
++ : "r" (sum << 16), "0" (sum)
++ : "r8");
++ return sum;
++ barrier();
++}
++
++
++/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
++
++
++extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ barrier();
++ __asm__ __volatile__(
++ "add %0, %1, %0\n"
++ "cmpltu r8, %0, %1\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %2, %0\n"
++ "cmpltu r8, %0, %2\n"
++ "add %0, %0, r8\n" /* add carry */
++ "add %0, %3, %0\n"
++ "cmpltu r8, %0, %3\n"
++ "add %0, %0, r8\n" /* add carry */
++ : "=r" (sum), "=r" (saddr)
++ : "r" (daddr), "r" ( (ntohs(len)<<16) + (proto*256) ),
++ "0" (sum),
++ "1" (saddr)
++ : "r8");
++
++ return sum;
++ barrier();
++}
++
++
++#endif /* (__NIOS2_CHECKSUM_H) */
+--- linux/include/asm-nios2nommu/cprefix.h
++++ linux/include/asm-nios2nommu/cprefix.h
+@@ -0,0 +1,38 @@
++/* cprefix.h: This file is included by assembly source which needs
++ * to know what the c-label prefixes are. The newer versions
++ * of cpp that come with gcc predefine such things to help
++ * us out. The reason this stuff is needed is to make
++ * solaris compiles of the kernel work.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_CPREFIX_H
++#define __NIOS2_CPREFIX_H
++
++#define C_LABEL_PREFIX
++
++#define CONCAT(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a##b
++
++#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name)
++
++#endif /* !(__NIOS2_CPREFIX_H) */
+--- linux/include/asm-nios2nommu/cpumask.h
++++ linux/include/asm-nios2nommu/cpumask.h
+@@ -0,0 +1,28 @@
++/*
++ * All rights reserved.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_CPUMASK_H
++#define _ASM_NIOS2NOMMU_CPUMASK_H
++
++#include <asm-generic/cpumask.h>
++
++#endif /* _ASM_NIOS2NOMMU_CPUMASK_H */
+--- linux/include/asm-nios2nommu/current.h
++++ linux/include/asm-nios2nommu/current.h
+@@ -0,0 +1,39 @@
++#ifndef _NIOS2NOMMU_CURRENT_H
++#define _NIOS2NOMMU_CURRENT_H
++/*
++ * current.h
++ * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
++ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
++ * (C) Copyright 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/thread_info.h>
++
++struct task_struct;
++
++static inline struct task_struct *get_current(void)
++{
++ return(current_thread_info()->task);
++}
++
++#define current get_current()
++
++#endif /* _NIOS2NOMMU_CURRENT_H */
+--- linux/include/asm-nios2nommu/delay.h
++++ linux/include/asm-nios2nommu/delay.h
+@@ -0,0 +1,96 @@
++#ifndef _NIOS_DELAY_H
++#define _NIOS_DELAY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/delay.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/param.h>
++
++extern __inline__ void __delay(unsigned long loops)
++{
++ int dummy;
++
++ __asm__ __volatile__(
++ "1: \n\t"
++ " beq %0,zero,2f\n\t"
++ " addi %0, %0, -1\n\t"
++ " br 1b\n\t"
++ "2: \n\t"
++
++ : "=r" (dummy) /* Need output for optimizer */
++
++ : "0" (loops) /* %0 Input */
++ );
++}
++
++/*
++ * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so
++ * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32.
++ *
++ * The mul instruction gives us loops = (a * b) / 2^32.
++ * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226
++ * because this lets us support a wide range of HZ and
++ * loops_per_jiffy values without either a or b overflowing 2^32.
++ * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and
++ * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280
++ * (which corresponds to ~3800 bogomips at HZ = 100).
++ * -- paulus
++ */
++#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */
++#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */
++
++extern unsigned long loops_per_jiffy;
++
++extern __inline__ void __udelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 226));
++ __delay(loops);
++}
++
++extern __inline__ void __ndelay(unsigned int x)
++{
++ unsigned int loops;
++
++ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
++ "r" (x), "r" (loops_per_jiffy * 5));
++ __delay(loops);
++}
++
++extern void __bad_udelay(void); /* deliberately undefined */
++extern void __bad_ndelay(void); /* deliberately undefined */
++
++#define udelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_UDELAY? __bad_udelay(): __udelay((n) * (19 * HZ))) : \
++ __udelay((n) * (19 * HZ)))
++
++#define ndelay(n) (__builtin_constant_p(n)? \
++ ((n) > __MAX_NDELAY? __bad_ndelay(): __ndelay((n) * HZ)) : \
++ __ndelay((n) * HZ))
++
++#define muldiv(a, b, c) (((a)*(b))/(c))
++
++#endif /* defined(_NIOS_DELAY_H) */
+--- linux/include/asm-nios2nommu/div64.h
++++ linux/include/asm-nios2nommu/div64.h
+@@ -0,0 +1,31 @@
++#ifndef __ASMNIOS_DIV64_H
++#define __ASMNIOS_DIV64_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/div64.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/div64.h>
++
++#endif
++
+--- linux/include/asm-nios2nommu/dma-mapping.h
++++ linux/include/asm-nios2nommu/dma-mapping.h
+@@ -0,0 +1,25 @@
++/*
++ * include/asm-s390/dma-mapping.h
++ *
++ * S390 version
++ *
++ * This file exists so that #include <dma-mapping.h> doesn't break anything.
++ */
++
++#ifndef _ASM_DMA_MAPPING_H
++#define _ASM_DMA_MAPPING_H
++
++static inline void *dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, int flag)
++{
++ BUG();
++ return 0;
++}
++
++static inline void dma_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ BUG();
++}
++
++#endif /* _ASM_DMA_MAPPING_H */
+--- linux/include/asm-nios2nommu/dma.h
++++ linux/include/asm-nios2nommu/dma.h
+@@ -0,0 +1,40 @@
++/* $Id: dma.h,v 1.5 2004/03/02 16:05:52 ken-h Exp $
++ *
++ * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
++ * Copyright 2004 (C) Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2_DMA_H
++#define _ASM_NIOS2_DMA_H
++
++#include <linux/kernel.h>
++#include <asm/asm-offsets.h>
++
++#define MAX_DMA_CHANNELS 2
++#define MAX_DMA_ADDRESS (LINUX_SDRAM_START)
++#define DMA_MODE_READ 1
++#define DMA_MODE_WRITE 2
++
++extern int get_dma_list(char *);
++extern int request_dma(unsigned int, const char *);
++extern void free_dma(unsigned int);
++
++#endif /* !(_ASM_NIOS2_DMA_H) */
+--- linux/include/asm-nios2nommu/elf.h
++++ linux/include/asm-nios2nommu/elf.h
+@@ -0,0 +1,141 @@
++#ifndef __NIOS2_ELF_H
++#define __NIOS2_ELF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/elf.h
++ *
++ * Nio2 ELF relocation types
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ * Mar/18/2004 xwt NiosII relocation types added
++ *
++ ---------------------------------------------------------------------*/
++
++// #include <linux/config.h>
++#include <asm/ptrace.h>
++#include <asm/user.h>
++
++#define R_NIOS2_NONE 0
++#define R_NIOS2_S16 1
++#define R_NIOS2_U16 2
++#define R_NIOS2_PCREL16 3
++#define R_NIOS2_CALL26 4
++#define R_NIOS2_IMM5 5
++#define R_NIOS2_CACHE_OPX 6
++#define R_NIOS2_IMM6 7
++#define R_NIOS2_IMM8 8
++#define R_NIOS2_HI16 9
++#define R_NIOS2_LO16 10
++#define R_NIOS2_HIADJ16 11
++#define R_NIOS2_BFD_RELOC_32 12
++#define R_NIOS2_BFD_RELOC_16 13
++#define R_NIOS2_BFD_RELOC_8 14
++#define R_NIOS2_GPREL 15
++#define R_NIOS2_GNU_VTINHERIT 16
++#define R_NIOS2_GNU_VTENTRY 17
++#define R_NIOS2_UJMP 18
++#define R_NIOS2_CJMP 19
++#define R_NIOS2_CALLR 20
++#define R_NIOS2_ALIGN 21
++/* Keep this the last entry. */
++#define R_NIOS2_NUM 22
++
++typedef unsigned long elf_greg_t;
++
++#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++typedef unsigned long elf_fpregset_t;
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++#define elf_check_arch(x) \
++ ((x)->e_machine == EM_ALTERA_NIOS2)
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2LSB
++#define ELF_ARCH EM_ALTERA_NIOS2
++
++#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
++ use of this is to invoke "./ld.so someprog" to test out a new version of
++ the loader. We need to make sure that it is out of the way of the program
++ that it will "exec", and that there is sufficient room for the brk. */
++
++#define ELF_ET_DYN_BASE 0xD0000000UL
++
++/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
++ now struct_user_regs, they are different) */
++
++#define ELF_CORE_COPY_REGS(pr_reg, regs) \
++ /* Bleech. */ \
++ pr_reg[0] = regs->r1; \
++ pr_reg[1] = regs->r2; \
++ pr_reg[2] = regs->r3; \
++ pr_reg[3] = regs->r4; \
++ pr_reg[4] = regs->r5; \
++ pr_reg[5] = regs->r6; \
++ pr_reg[6] = regs->r7; \
++ pr_reg[7] = regs->r8; \
++ pr_reg[8] = regs->r9; \
++ pr_reg[9] = regs->r10; \
++ pr_reg[10] = regs->r11; \
++ pr_reg[11] = regs->r12; \
++ pr_reg[12] = regs->r13; \
++ pr_reg[13] = regs->r14; \
++ pr_reg[14] = regs->r15; \
++ pr_reg[23] = regs->sp; \
++ pr_reg[26] = regs->estatus; \
++ { \
++ struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \
++ pr_reg[15] = sw->r16; \
++ pr_reg[16] = sw->r17; \
++ pr_reg[17] = sw->r18; \
++ pr_reg[18] = sw->r19; \
++ pr_reg[19] = sw->r20; \
++ pr_reg[20] = sw->r21; \
++ pr_reg[21] = sw->r22; \
++ pr_reg[22] = sw->r23; \
++ pr_reg[24] = sw->fp; \
++ pr_reg[25] = sw->gp; \
++ }
++
++/* This yields a mask that user programs can use to figure out what
++ instruction set this cpu supports. */
++
++#define ELF_HWCAP (0)
++
++/* This yields a string that ld.so will use to load implementation
++ specific libraries for optimization. This is more specific in
++ intent than poking at uname or /proc/cpuinfo. */
++
++#define ELF_PLATFORM (NULL)
++
++#ifdef __KERNEL__
++#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
++#endif
++
++#endif
+--- linux/include/asm-nios2nommu/entry.h
++++ linux/include/asm-nios2nommu/entry.h
+@@ -0,0 +1,188 @@
++/*
++ * Hacked from m68knommu port.
++ *
++ * Copyright(C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_ENTRY_H
++#define __NIOS2NOMMU_ENTRY_H
++
++#ifdef __ASSEMBLY__
++
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/asm-offsets.h>
++
++/*
++ * Stack layout in 'ret_from_exception':
++ *
++ * This allows access to the syscall arguments in registers r4-r8
++ *
++ * 0(sp) - r8
++ * 4(sp) - r9
++ * 8(sp) - r10
++ * C(sp) - r11
++ * 10(sp) - r12
++ * 14(sp) - r13
++ * 18(sp) - r14
++ * 1C(sp) - r15
++ * 20(sp) - r1
++ * 24(sp) - r2
++ * 28(sp) - r3
++ * 2C(sp) - r4
++ * 30(sp) - r5
++ * 34(sp) - r6
++ * 38(sp) - r7
++ * 3C(sp) - orig_r2
++ * 40(sp) - ra
++ * 44(sp) - fp
++ * 48(sp) - sp
++ * 4C(sp) - gp
++ * 50(sp) - estatus
++ * 54(sp) - status_extension
++ * 58(sp) - ea
++ *
++ */
++
++/* process bits for task_struct.flags */
++PF_TRACESYS_OFF = 3
++PF_TRACESYS_BIT = 5
++PF_PTRACED_OFF = 3
++PF_PTRACED_BIT = 4
++PF_DTRACE_OFF = 1
++PF_DTRACE_BIT = 5
++
++LENOSYS = 38
++
++/*
++ * This defines the normal kernel pt-regs layout.
++ *
++ */
++
++/*
++ * Standard Nios2 interrupt entry and exit macros.
++ * Must be called with interrupts disabled.
++ */
++.macro SAVE_ALL
++ movia r24,status_extension // Read status extension
++ ldw r24,0(r24)
++ andi r24,r24,PS_S_ASM
++ bne r24,r0,1f // In supervisor mode, already on kernel stack
++ movia r24,_current_thread // Switch to current kernel stack
++ ldw r24,0(r24) // using the thread_info
++ addi r24,r24,THREAD_SIZE_ASM-PT_REGS_SIZE
++ stw sp,PT_SP(r24) // Save user stack before changing
++ mov sp,r24
++ br 2f
++
++1: mov r24,sp
++ addi sp,sp,-PT_REGS_SIZE // Backup the kernel stack pointer
++ stw r24,PT_SP(sp)
++2: stw r1,PT_R1(sp)
++ stw r2,PT_R2(sp)
++ stw r3,PT_R3(sp)
++ stw r4,PT_R4(sp)
++ stw r5,PT_R5(sp)
++ stw r6,PT_R6(sp)
++ stw r7,PT_R7(sp)
++ stw r8,PT_R8(sp)
++ stw r9,PT_R9(sp)
++ stw r10,PT_R10(sp)
++ stw r11,PT_R11(sp)
++ stw r12,PT_R12(sp)
++ stw r13,PT_R13(sp)
++ stw r14,PT_R14(sp)
++ stw r15,PT_R15(sp)
++ stw r2,PT_ORIG_R2(sp)
++ stw ra,PT_RA(sp)
++ stw fp,PT_FP(sp)
++ stw gp,PT_GP(sp)
++ rdctl r24,estatus
++ stw r24,PT_ESTATUS(sp)
++ movia r24,status_extension // Read status extension
++ ldw r1,0(r24)
++ stw r1,PT_STATUS_EXTENSION(sp) // Store user/supervisor status
++ ORI32 r1,r1,PS_S_ASM // Set supervisor mode
++ stw r1,0(r24)
++ stw ea,PT_EA(sp)
++.endm
++
++.macro RESTORE_ALL
++ ldw r1,PT_STATUS_EXTENSION(sp) // Restore user/supervisor status
++ movia r24,status_extension
++ stw r1,0(r24)
++ ldw r1,PT_R1(sp) // Restore registers
++ ldw r2,PT_R2(sp)
++ ldw r3,PT_R3(sp)
++ ldw r4,PT_R4(sp)
++ ldw r5,PT_R5(sp)
++ ldw r6,PT_R6(sp)
++ ldw r7,PT_R7(sp)
++ ldw r8,PT_R8(sp)
++ ldw r9,PT_R9(sp)
++ ldw r10,PT_R10(sp)
++ ldw r11,PT_R11(sp)
++ ldw r12,PT_R12(sp)
++ ldw r13,PT_R13(sp)
++ ldw r14,PT_R14(sp)
++ ldw r15,PT_R15(sp)
++ ldw ra,PT_RA(sp)
++ ldw fp,PT_FP(sp)
++ ldw gp,PT_GP(sp)
++ ldw r24,PT_ESTATUS(sp)
++ wrctl estatus,r24
++ ldw ea,PT_EA(sp)
++ ldw sp,PT_SP(sp) // Restore sp last
++.endm
++
++.macro SAVE_SWITCH_STACK
++ addi sp,sp,-SWITCH_STACK_SIZE
++ stw r16,SW_R16(sp)
++ stw r17,SW_R17(sp)
++ stw r18,SW_R18(sp)
++ stw r19,SW_R19(sp)
++ stw r20,SW_R20(sp)
++ stw r21,SW_R21(sp)
++ stw r22,SW_R22(sp)
++ stw r23,SW_R23(sp)
++ stw fp,SW_FP(sp)
++ stw gp,SW_GP(sp)
++ stw ra,SW_RA(sp)
++.endm
++
++.macro RESTORE_SWITCH_STACK
++ ldw r16,SW_R16(sp)
++ ldw r17,SW_R17(sp)
++ ldw r18,SW_R18(sp)
++ ldw r19,SW_R19(sp)
++ ldw r20,SW_R20(sp)
++ ldw r21,SW_R21(sp)
++ ldw r22,SW_R22(sp)
++ ldw r23,SW_R23(sp)
++ ldw fp,SW_FP(sp)
++ ldw gp,SW_GP(sp)
++ ldw ra,SW_RA(sp)
++ addi sp,sp,SWITCH_STACK_SIZE
++.endm
++
++#endif /* __ASSEMBLY__ */
++#endif /* __NIOS2NOMMU_ENTRY_H */
+--- linux/include/asm-nios2nommu/errno.h
++++ linux/include/asm-nios2nommu/errno.h
+@@ -0,0 +1,6 @@
++#ifndef _NIOS2NOMMU_ERRNO_H
++#define _NIOS2NOMMU_ERRNO_H
++
++#include <asm-generic/errno.h>
++
++#endif /* _NIOS2NOMMU_ERRNO_H */
+--- linux/include/asm-nios2nommu/fcntl.h
++++ linux/include/asm-nios2nommu/fcntl.h
+@@ -0,0 +1,110 @@
++/*
++ * This file came from the m68k port.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_FCNTL_H
++#define _NIOS2_FCNTL_H
++
++/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
++ located on an ext2 file system */
++#define O_ACCMODE 0003
++#define O_RDONLY 00
++#define O_WRONLY 01
++#define O_RDWR 02
++#define O_CREAT 0100 /* not fcntl */
++#define O_EXCL 0200 /* not fcntl */
++#define O_NOCTTY 0400 /* not fcntl */
++#define O_TRUNC 01000 /* not fcntl */
++#define O_APPEND 02000
++#define O_NONBLOCK 04000
++#define O_NDELAY O_NONBLOCK
++#define O_SYNC 010000
++#define FASYNC 020000 /* fcntl, for BSD compatibility */
++#define O_DIRECTORY 040000 /* must be a directory */
++#define O_NOFOLLOW 0100000 /* don't follow links */
++#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
++#define O_LARGEFILE 0400000
++#define O_NOATIME 01000000
++
++#define F_DUPFD 0 /* dup */
++#define F_GETFD 1 /* get close_on_exec */
++#define F_SETFD 2 /* set/clear close_on_exec */
++#define F_GETFL 3 /* get file->f_flags */
++#define F_SETFL 4 /* set file->f_flags */
++#define F_GETLK 5
++#define F_SETLK 6
++#define F_SETLKW 7
++
++#define F_SETOWN 8 /* for sockets. */
++#define F_GETOWN 9 /* for sockets. */
++#define F_SETSIG 10 /* for sockets. */
++#define F_GETSIG 11 /* for sockets. */
++
++#define F_GETLK64 12 /* using 'struct flock64' */
++#define F_SETLK64 13
++#define F_SETLKW64 14
++
++/* for F_[GET|SET]FL */
++#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
++
++/* for posix fcntl() and lockf() */
++#define F_RDLCK 0
++#define F_WRLCK 1
++#define F_UNLCK 2
++
++/* for old implementation of bsd flock () */
++#define F_EXLCK 4 /* or 3 */
++#define F_SHLCK 8 /* or 4 */
++
++/* for leases */
++#define F_INPROGRESS 16
++
++/* operations for bsd flock(), also used by the kernel implementation */
++#define LOCK_SH 1 /* shared lock */
++#define LOCK_EX 2 /* exclusive lock */
++#define LOCK_NB 4 /* or'd with one of the above to prevent
++ blocking */
++#define LOCK_UN 8 /* remove lock */
++
++#define LOCK_MAND 32 /* This is a mandatory flock */
++#define LOCK_READ 64 /* ... Which allows concurrent read operations */
++#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
++#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
++
++struct flock {
++ short l_type;
++ short l_whence;
++ off_t l_start;
++ off_t l_len;
++ pid_t l_pid;
++};
++
++struct flock64 {
++ short l_type;
++ short l_whence;
++ loff_t l_start;
++ loff_t l_len;
++ pid_t l_pid;
++};
++
++#define F_LINUX_SPECIFIC_BASE 1024
++#endif /* _NIOS2_FCNTL_H */
+--- linux/include/asm-nios2nommu/flat.h
++++ linux/include/asm-nios2nommu/flat.h
+@@ -0,0 +1,126 @@
++/*
++ * include/asm-nios2nommu/flat.h -- uClinux bFLT relocations
++ *
++ * Copyright (C) 2004,05 Microtronix Datacom Ltd
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License. See the file COPYING in the main directory of this
++ * archive for more details.
++ *
++ * Written by Wentao Xu <wentao@microtronix.com>
++ */
++
++#ifndef __NIOS2_FLAT_H__
++#define __NIOS2_FLAT_H__
++
++#define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
++
++/* The stack is 64-bit aligned for Nios II, so (sp - 1) shall
++ * be 64-bit aligned, where -1 is for argc
++ */
++#define flat_stack_align(sp) (sp = (unsigned long *)(((unsigned long)sp - 1) & (-8)))
++
++/* The uClibc port for Nios II expects the argc is followed by argv and envp */
++#define flat_argvp_envp_on_stack() 1
++
++#define flat_old_ram_flag(flags) (flags)
++
++/* We store the type of relocation in the top 4 bits of the `relval.' */
++
++/* Convert a relocation entry into an address. */
++static inline unsigned long
++flat_get_relocate_addr (unsigned long relval)
++{
++ return relval & 0x0fffffff; /* Mask out top 4-bits */
++}
++
++#define FLAT_NIOS2_RELOC_TYPE(relval) ((relval) >> 28)
++
++#define FLAT_NIOS2_R_32 0 /* Normal 32-bit reloc */
++#define FLAT_NIOS2_R_HI_LO 1 /* High 16-bits + low 16-bits field */
++#define FLAT_NIOS2_R_HIADJ_LO 2 /* High 16-bits adjust + low 16-bits field */
++#define FLAT_NIOS2_R_CALL26 4 /* Call imm26 */
++
++/* Extract the address to be relocated from the symbol reference at rp;
++ * relval is the raw relocation-table entry from which RP is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
++ unsigned long relval,
++ unsigned long flags)
++{
++ switch (FLAT_NIOS2_RELOC_TYPE(relval))
++ {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. The loader expect it in bigger endian */
++ return htonl(*rp);
++
++ case FLAT_NIOS2_R_HI_LO:
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ return htonl ((((rp[0] >> 6) & 0xFFFF) << 16 ) |
++ ((rp[1] >> 6) & 0xFFFF));
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ /* get the two 16-bit immediate value from instructions, then
++ * construct a 32-bit value. Again the loader expect bigger endian
++ */
++ unsigned int low, high;
++ high = (rp[0] >> 6) & 0xFFFF;
++ low = (rp[1] >> 6) & 0xFFFF;
++
++ if ((low >> 15) & 1) high--;
++
++ return htonl ((high << 16 ) | low );
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the 26-bit immediate value is actually 28-bit */
++ return htonl(((*rp) >> 6) << 2);
++
++ default:
++ return ~0; /* bogus value */
++ }
++}
++
++/* Insert the address addr into the symbol reference at rp;
++ * relval is the raw relocation-table entry from which rp is derived.
++ * rp shall always be 32-bit aligned
++ */
++static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
++ unsigned long relval)
++{
++ unsigned long exist_val;
++ switch (FLAT_NIOS2_RELOC_TYPE (relval)) {
++ case FLAT_NIOS2_R_32:
++ /* Simple 32-bit address. */
++ *rp = addr;
++ break;
++
++ case FLAT_NIOS2_R_HI_LO:
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | (addr >> 16)) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++
++ case FLAT_NIOS2_R_HIADJ_LO:
++ {
++ unsigned int high = (addr >> 16);
++ if ((addr >> 15) & 1)
++ high = (high + 1) & 0xFFFF;
++ exist_val = rp[0];
++ rp[0] = ((((exist_val >> 22) << 16) | high) << 6) | (exist_val & 0x3F);
++ exist_val = rp[1];
++ rp[1] = ((((exist_val >> 22) << 16) | (addr & 0xFFFF)) << 6) | (exist_val & 0x3F);
++ break;
++ }
++ case FLAT_NIOS2_R_CALL26:
++ /* the opcode of CALL is 0, so just store the value */
++ *rp = ((addr >> 2) << 6);
++ break;
++ }
++}
++
++#endif /* __NIOS2_FLAT_H__ */
+--- linux/include/asm-nios2nommu/hardirq.h
++++ linux/include/asm-nios2nommu/hardirq.h
+@@ -0,0 +1,85 @@
++/*
++ * Ported from m68knommu
++ *
++ * Copyright (C) 2003, Microtronix Datacom Ltd.
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HARDIRQ_H
++#define __NIOS2_HARDIRQ_H
++
++// #include <linux/config.h>
++#include <linux/cache.h>
++#include <linux/threads.h>
++
++typedef struct {
++ unsigned int __softirq_pending;
++ unsigned int __syscall_count;
++ struct task_struct * __ksoftirqd_task;
++} ____cacheline_aligned irq_cpustat_t;
++
++#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
++
++/*
++ * We put the hardirq and softirq counter into the preemption
++ * counter. The bitmask has the following meaning:
++ *
++ * - bits 0-7 are the preemption count (max preemption depth: 256)
++ * - bits 8-15 are the softirq count (max # of softirqs: 256)
++ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
++ *
++ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
++ *
++ * PREEMPT_MASK: 0x000000ff
++ * HARDIRQ_MASK: 0x0000ff00
++ * SOFTIRQ_MASK: 0x00ff0000
++ */
++
++#define PREEMPT_BITS 8
++#define SOFTIRQ_BITS 8
++#define HARDIRQ_BITS 8
++
++#define PREEMPT_SHIFT 0
++#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
++#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
++
++/*
++ * The hardirq mask has to be large enough to have
++ * space for potentially all IRQ sources in the system
++ * nesting on a single CPU:
++ */
++#if (1 << HARDIRQ_BITS) < NR_IRQS
++# error HARDIRQ_BITS is too low!
++#endif
++
++#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
++#define irq_exit() \
++do { \
++ preempt_count() -= IRQ_EXIT_OFFSET; \
++ if (!in_interrupt() && softirq_pending(smp_processor_id())) \
++ do_softirq(); \
++ preempt_enable_no_resched(); \
++} while (0)
++
++#ifdef CONFIG_SMP
++# error nios2nommu SMP is not available
++#endif /* CONFIG_SMP */
++
++#endif /* __NIOS2_HARDIRQ_H */
+--- linux/include/asm-nios2nommu/hdreg.h
++++ linux/include/asm-nios2nommu/hdreg.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2002 Wentau Xu (www.microtronix.com)
++ * copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_HDREG_H
++#define __NIOS2_HDREG_H
++
++typedef unsigned long ide_ioreg_t;
++
++#endif /* __NIOS2_HDREG_H */
+--- linux/include/asm-nios2nommu/hw_irq.h
++++ linux/include/asm-nios2nommu/hw_irq.h
+@@ -0,0 +1,16 @@
++#ifndef _ASM_HW_IRQ_H
++#define _ASM_HW_IRQ_H
++
++/*
++ * linux/include/asm/hw_irq.h
++ *
++ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
++ *
++ * moved some of the old arch/i386/kernel/irq.h to here. VY
++ *
++ * IRQ/IPI changes taken from work by Thomas Radke
++ * <tomsoft@informatik.tu-chemnitz.de>
++ */
++
++
++#endif /* _ASM_HW_IRQ_H */
+--- linux/include/asm-nios2nommu/ide.h
++++ linux/include/asm-nios2nommu/ide.h
+@@ -0,0 +1,47 @@
++/*
++ * linux/include/asm-niosnommu2/ide.h
++ *
++ * Copyright (C) 1994-1996 Linus Torvalds & authors
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASMNIOS2_IDE_H
++#define __ASMNIOS2_IDE_H
++
++#ifdef __KERNEL__
++#undef MAX_HWIFS /* we're going to force it */
++
++#ifndef MAX_HWIFS
++#define MAX_HWIFS 1
++#endif
++
++#define IDE_ARCH_OBSOLETE_INIT
++#define IDE_ARCH_OBSOLETE_DEFAULTS
++#define ide_default_io_base(i) ((unsigned long)na_ide_ide)
++#define ide_default_irq(b) (na_ide_ide_irq)
++#define ide_init_default_irq(base) ide_default_irq(base)
++#define ide_default_io_ctl(base) ((base) + (0xE*4))
++
++#include <asm-generic/ide_iops.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASMNIOS2_IDE_H */
+--- linux/include/asm-nios2nommu/init.h
++++ linux/include/asm-nios2nommu/init.h
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++#error "<asm/init.h> should never be used - use <linux/init.h> instead"
+--- linux/include/asm-nios2nommu/io.h
++++ linux/include/asm-nios2nommu/io.h
+@@ -0,0 +1,239 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_IO_H
++#define __NIOS2_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/kernel.h>
++
++#include <asm/page.h> /* IO address mapping routines need this */
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++extern void insw(unsigned long port, void *dst, unsigned long count);
++extern void outsw(unsigned long port, void *src, unsigned long count);
++extern void insl(unsigned long port, void *dst, unsigned long count);
++extern void outsl(unsigned long port, void *src, unsigned long count);
++
++
++/*
++ * readX/writeX() are used to access memory mapped devices. On some
++ * architectures the memory mapped IO stuff needs to be accessed
++ * differently. On the Nios architecture, we just read/write the
++ * memory location directly.
++ */
++
++#define readb(addr) \
++({ \
++ unsigned char __res;\
++ __asm__ __volatile__( \
++ "ldbuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readw(addr) \
++({ \
++ unsigned short __res;\
++ __asm__ __volatile__( \
++ "ldhuio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define readl(addr) \
++({ \
++ unsigned int __res;\
++ __asm__ __volatile__( \
++ "ldwio %0, 0(%1)" \
++ : "=r"(__res) \
++ : "r" (addr)); \
++ __res; \
++})
++
++#define writeb(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stbio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writew(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "sthio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define writel(b,addr) \
++({ \
++ __asm__ __volatile__( \
++ "stwio %0, 0(%1)" \
++ : : "r"(b), "r" (addr)); \
++})
++
++#define __raw_readb readb
++#define __raw_readw readw
++#define __raw_readl readl
++#define __raw_writeb writeb
++#define __raw_writew writew
++#define __raw_writel writel
++
++
++/*
++ * make the short names macros so specific devices
++ * can override them as required
++ */
++
++#define memset_io(addr,c,len) memset((void *)(((unsigned int)(addr)) | 0x80000000),(c),(len))
++#define memcpy_fromio(to,from,len) memcpy((to),(void *)(((unsigned int)(from)) | 0x80000000),(len))
++#define memcpy_toio(to,from,len) memcpy((void *)(((unsigned int)(to)) | 0x80000000),(from),(len))
++
++#define inb(addr) readb(addr)
++#define inw(addr) readw(addr)
++#define inl(addr) readl(addr)
++
++#define outb(x,addr) ((void) writeb(x,addr))
++#define outw(x,addr) ((void) writew(x,addr))
++#define outl(x,addr) ((void) writel(x,addr))
++
++#define inb_p(addr) inb(addr)
++#define inw_p(addr) inw(addr)
++#define inl_p(addr) inl(addr)
++
++#define outb_p(x,addr) outb(x,addr)
++#define outw_p(x,addr) outw(x,addr)
++#define outl_p(x,addr) outl(x,addr)
++
++
++
++extern inline void insb(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)dst;
++ while (count--)
++ *p++ = inb(port);
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _insw(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)dst;
++ while (count--)
++ *p++ = inw(port);
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned destination pointer */
++extern inline void _insl(unsigned long port, void *dst, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)dst;
++ while (count--)
++ *p++ = inl(port);
++}
++
++extern inline void outsb(unsigned long port, void *src, unsigned long count)
++{
++ unsigned char *p=(unsigned char*)src;
++ while (count--)
++ outb( *p++, port );
++}
++
++/* See arch/niosnommu/io.c for optimized version */
++extern inline void _outsw(unsigned long port, void *src, unsigned long count)
++{
++ unsigned short *p=(unsigned short*)src;
++ while (count--)
++ outw( *p++, port );
++}
++
++/* See arch/niosnommu/kernel/io.c for unaligned source pointer */
++extern inline void _outsl(unsigned long port, void *src, unsigned long count)
++{
++ unsigned long *p=(unsigned long*)src;
++ while (count--)
++ outl( *p++, port );
++}
++
++
++
++extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
++ int bus, int rdonly)
++{
++ return;
++}
++
++//vic - copied from m68knommu
++
++/* Values for nocacheflag and cmode */
++#define IOMAP_FULL_CACHING 0
++#define IOMAP_NOCACHE_SER 1
++#define IOMAP_NOCACHE_NONSER 2
++#define IOMAP_WRITETHROUGH 3
++
++extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
++extern void __iounmap(void *addr, unsigned long size);
++
++extern inline void *ioremap(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
++}
++extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
++}
++extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
++{
++ return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
++}
++
++extern void iounmap(void *addr);
++
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define dma_cache_inv(_start,_size) do { } while (0)
++#define dma_cache_wback(_start,_size) do { } while (0)
++#define dma_cache_wback_inv(_start,_size) do { } while (0)
++
++/* Pages to physical address... */
++#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
++#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#endif /* __KERNEL__ */
++
++#endif /* !(__NIOS2_IO_H) */
++
+--- linux/include/asm-nios2nommu/ioctl.h
++++ linux/include/asm-nios2nommu/ioctl.h
+@@ -0,0 +1,100 @@
++/* $Id: ioctl.h,v 1.3 2004/02/12 23:06:40 ken-h Exp $
++ *
++ * linux/ioctl.h for Linux by H.H. Bergman.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_IOCTL_H
++#define _NIOS2_IOCTL_H
++
++/* ioctl command encoding: 32 bits total, command in lower 16 bits,
++ * size of the parameter structure in the lower 14 bits of the
++ * upper 16 bits.
++ * Encoding the size of the parameter structure in the ioctl request
++ * is useful for catching programs compiled with old versions
++ * and to avoid overwriting user space outside the user buffer area.
++ * The highest 2 bits are reserved for indicating the ``access mode''.
++ * NOTE: This limits the max parameter size to 16kB -1 !
++ */
++
++/*
++ * I don't really have any idea about what this should look like, so
++ * for the time being, this is heavily based on the PC definitions.
++ */
++
++/*
++ * The following is for compatibility across the various Linux
++ * platforms. The i386 ioctl numbering scheme doesn't really enforce
++ * a type field. De facto, however, the top 8 bits of the lower 16
++ * bits are indeed used as a type field, so we might just as well make
++ * this explicit here. Please be sure to use the decoding macros
++ * below from now on.
++ */
++#define _IOC_NRBITS 8
++#define _IOC_TYPEBITS 8
++#define _IOC_SIZEBITS 14
++#define _IOC_DIRBITS 2
++
++#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
++#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
++#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
++#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
++
++#define _IOC_NRSHIFT 0
++#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
++#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
++#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
++
++/*
++ * Direction bits.
++ */
++#define _IOC_NONE 0U
++#define _IOC_WRITE 1U
++#define _IOC_READ 2U
++
++#define _IOC(dir,type,nr,size) \
++ (((dir) << _IOC_DIRSHIFT) | \
++ ((type) << _IOC_TYPESHIFT) | \
++ ((nr) << _IOC_NRSHIFT) | \
++ ((size) << _IOC_SIZESHIFT))
++
++/* used to create numbers */
++#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
++#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
++#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
++#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
++
++/* used to decode ioctl numbers.. */
++#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
++#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
++#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
++#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
++
++/* ...and for the drivers/sound files... */
++
++#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
++#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
++#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
++#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
++#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
++
++#endif /* _NIOS2_IOCTL_H */
+--- linux/include/asm-nios2nommu/ioctls.h
++++ linux/include/asm-nios2nommu/ioctls.h
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ARCH_NIOS2_IOCTLS_H__
++#define __ARCH_NIOS2_IOCTLS_H__
++
++#include <asm/ioctl.h>
++
++/* 0x54 is just a magic number to make these relatively unique ('T') */
++
++#define TCGETS 0x5401
++#define TCSETS 0x5402
++#define TCSETSW 0x5403
++#define TCSETSF 0x5404
++#define TCGETA 0x5405
++#define TCSETA 0x5406
++#define TCSETAW 0x5407
++#define TCSETAF 0x5408
++#define TCSBRK 0x5409
++#define TCXONC 0x540A
++#define TCFLSH 0x540B
++#define TIOCEXCL 0x540C
++#define TIOCNXCL 0x540D
++#define TIOCSCTTY 0x540E
++#define TIOCGPGRP 0x540F
++#define TIOCSPGRP 0x5410
++#define TIOCOUTQ 0x5411
++#define TIOCSTI 0x5412
++#define TIOCGWINSZ 0x5413
++#define TIOCSWINSZ 0x5414
++#define TIOCMGET 0x5415
++#define TIOCMBIS 0x5416
++#define TIOCMBIC 0x5417
++#define TIOCMSET 0x5418
++#define TIOCGSOFTCAR 0x5419
++#define TIOCSSOFTCAR 0x541A
++#define FIONREAD 0x541B
++#define TIOCINQ FIONREAD
++#define TIOCLINUX 0x541C
++#define TIOCCONS 0x541D
++#define TIOCGSERIAL 0x541E
++#define TIOCSSERIAL 0x541F
++#define TIOCPKT 0x5420
++#define FIONBIO 0x5421
++#define TIOCNOTTY 0x5422
++#define TIOCSETD 0x5423
++#define TIOCGETD 0x5424
++#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
++#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
++#define TIOCSBRK 0x5427 /* BSD compatibility */
++#define TIOCCBRK 0x5428 /* BSD compatibility */
++#define TIOCGSID 0x5429 /* Return the session ID of FD */
++#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
++#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
++
++#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
++#define FIOCLEX 0x5451
++#define FIOASYNC 0x5452
++#define TIOCSERCONFIG 0x5453
++#define TIOCSERGWILD 0x5454
++#define TIOCSERSWILD 0x5455
++#define TIOCGLCKTRMIOS 0x5456
++#define TIOCSLCKTRMIOS 0x5457
++#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
++#define TIOCSERGETLSR 0x5459 /* Get line status register */
++#define TIOCSERGETMULTI 0x545A /* Get multiport config */
++#define TIOCSERSETMULTI 0x545B /* Set multiport config */
++
++#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
++#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
++#define FIOQSIZE 0x545E
++
++/* Used for packet mode */
++#define TIOCPKT_DATA 0
++#define TIOCPKT_FLUSHREAD 1
++#define TIOCPKT_FLUSHWRITE 2
++#define TIOCPKT_STOP 4
++#define TIOCPKT_START 8
++#define TIOCPKT_NOSTOP 16
++#define TIOCPKT_DOSTOP 32
++
++#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
++
++#endif /* __ARCH_NIOS2_IOCTLS_H__ */
+--- linux/include/asm-nios2nommu/ipc.h
++++ linux/include/asm-nios2nommu/ipc.h
+@@ -0,0 +1,51 @@
++#ifndef __NIOS2_IPC_H__
++#define __NIOS2_IPC_H__
++
++/* Copied from sparc version
++ * These are used to wrap system calls on the Nios.
++ *
++ * See arch/niosnommu/kernel/sys_nios.c for ugly details..
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++struct ipc_kludge {
++ struct msgbuf *msgp;
++ long msgtyp;
++};
++
++#define SEMOP 1
++#define SEMGET 2
++#define SEMCTL 3
++#define MSGSND 11
++#define MSGRCV 12
++#define MSGGET 13
++#define MSGCTL 14
++#define SHMAT 21
++#define SHMDT 22
++#define SHMGET 23
++#define SHMCTL 24
++
++/* Used by the DIPC package, try and avoid reusing it */
++#define DIPC 25
++
++#define IPCCALL(version,op) ((version)<<16 | (op))
++
++#endif
+--- linux/include/asm-nios2nommu/ipcbuf.h
++++ linux/include/asm-nios2nommu/ipcbuf.h
+@@ -0,0 +1,49 @@
++#ifndef __NIOS2_IPCBUF_H__
++#define __NIOS2_IPCBUF_H__
++
++/* Copied from asm-m68k/ipcbuf.h
++ * The user_ipc_perm structure for Nios architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 32-bit mode_t and seq
++ * - 2 miscellaneous 32-bit values
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ */
++
++struct ipc64_perm
++{
++ __kernel_key_t key;
++ __kernel_uid32_t uid;
++ __kernel_gid32_t gid;
++ __kernel_uid32_t cuid;
++ __kernel_gid32_t cgid;
++ __kernel_mode_t mode;
++ unsigned short __pad1;
++ unsigned short seq;
++ unsigned short __pad2;
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* __NIOS2_IPCBUF_H__ */
+--- linux/include/asm-nios2nommu/irq.h
++++ linux/include/asm-nios2nommu/irq.h
+@@ -0,0 +1,182 @@
++/*
++ * 21Mar2001 1.1 dgt/microtronix
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_IRQ_H_
++#define _NIOS2NOMMU_IRQ_H_
++
++extern void disable_irq(unsigned int);
++extern void enable_irq(unsigned int);
++
++// #include <linux/config.h>
++#include <linux/interrupt.h>
++
++#define SYS_IRQS 32
++#define NR_IRQS SYS_IRQS
++
++/*
++ * Interrupt source definitions
++ * General interrupt sources are the level 1-7.
++ * Adding an interrupt service routine for one of these sources
++ * results in the addition of that routine to a chain of routines.
++ * Each one is called in succession. Each individual interrupt
++ * service routine should determine if the device associated with
++ * that routine requires service.
++ */
++
++#define IRQ01 (1) /* level 1 interrupt */
++#define IRQ02 (2) /* level 2 interrupt */
++#define IRQ03 (3) /* level 3 interrupt */
++#define IRQ04 (4) /* level 4 interrupt */
++#define IRQ05 (5) /* level 5 interrupt */
++#define IRQ06 (6) /* level 6 interrupt */
++#define IRQ07 (7) /* level 7 interrupt */
++#define IRQ08 (8) /* level 8 interrupt */
++#define IRQ09 (9) /* level 9 interrupt */
++#define IRQ0A (10) /* level 10 interrupt */
++#define IRQ0B (11) /* level 11 interrupt */
++#define IRQ0C (12) /* level 12 interrupt */
++#define IRQ0D (13) /* level 13 interrupt */
++#define IRQ0E (14) /* level 14 interrupt */
++#define IRQ0F (15) /* level 15 interrupt */
++#define IRQ10 (16) /* level 16 interrupt */
++#define IRQ12 (17) /* level 17 interrupt */
++#define IRQ13 (18) /* level 18 interrupt */
++#define IRQ14 (19) /* level 19 interrupt */
++#define IRQ15 (20) /* level 20 interrupt */
++#define IRQ16 (21) /* level 21 interrupt */
++#define IRQ17 (22) /* level 22 interrupt */
++#define IRQ18 (23) /* level 23 interrupt */
++#define IRQ19 (24) /* level 24 interrupt */
++#define IRQ1A (25) /* level 25 interrupt */
++#define IRQ1B (26) /* level 26 interrupt */
++#define IRQ1C (27) /* level 27 interrupt */
++#define IRQ1D (28) /* level 28 interrupt */
++#define IRQ1E (29) /* level 29 interrupt */
++#define IRQ1F (30) /* level 30 interrupt */
++#define IRQ20 (31) /* level 31 interrupt */
++#define IRQ21 (32) /* level 32 interrupt */
++
++#define IRQMAX IRQ21
++
++/*
++ * "Generic" interrupt sources
++ */
++
++/*
++ * Machine specific interrupt sources.
++ *
++ * Adding an interrupt service routine for a source with this bit
++ * set indicates a special machine specific interrupt source.
++ * The machine specific files define these sources.
++ *
++ * Removed, they are not used by any one.
++ */
++
++/*
++ * various flags for request_irq()
++ */
++#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
++#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
++#define IRQ_FLG_FAST (0x0004)
++#define IRQ_FLG_SLOW (0x0008)
++#define IRQ_FLG_STD (0x8000) /* internally used */
++
++/*
++ * Functions to set and clear the interrupt mask.
++ */
++
++/*
++ * Use a zero to clean the bit.
++ */
++static inline void clrimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "and r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * Use a one to set the bit.
++ */
++static inline void setimr(int mask)
++{
++ int flags;
++
++ local_irq_save(flags);
++ __asm__ __volatile__(
++ "rdctl r8, ienable\n"
++ "or r8,r8,%0\n"
++ "wrctl ienable, r8\n"
++ : /* No output */
++ : "r" (mask)
++ : "r8");
++ local_irq_restore(flags);
++}
++
++/*
++ * This structure is used to chain together the ISRs for a particular
++ * interrupt source (if it supports chaining).
++ */
++typedef struct irq_node {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++ struct irq_node *next;
++} irq_node_t;
++
++/*
++ * This function returns a new irq_node_t
++ */
++extern irq_node_t *new_irq_node(void);
++
++/*
++ * This structure has only 4 elements for speed reasons
++ */
++typedef struct irq_handler {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ unsigned long flags;
++ void *dev_id;
++ const char *devname;
++} irq_handler_t;
++
++/* count of spurious interrupts */
++extern volatile unsigned int num_spurious;
++
++#define disable_irq_nosync(i) disable_irq(i)
++
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#endif /* _NIOS2NOMMU_IRQ_H_ */
+--- linux/include/asm-nios2nommu/kmap_types.h
++++ linux/include/asm-nios2nommu/kmap_types.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_KMAP_TYPES_H
++#define _ASM_KMAP_TYPES_H
++
++enum km_type {
++ KM_BOUNCE_READ,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ KM_TYPE_NR
++};
++
++#endif
+--- linux/include/asm-nios2nommu/linkage.h
++++ linux/include/asm-nios2nommu/linkage.h
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __ASM_LINKAGE_H
++#define __ASM_LINKAGE_H
++
++#define __ALIGN .align 3
++#define __ALIGN_STR ".align 3"
++
++#endif
+--- linux/include/asm-nios2nommu/linux_logo.h
++++ linux/include/asm-nios2nommu/linux_logo.h
+@@ -0,0 +1,953 @@
++/* $Id: linux_logo.h,v 1.3 2004/02/12 23:06:40 ken-h Exp $
++ * include/asm-nios/linux_logo.h: This is a linux logo
++ * to be displayed on boot.
++ *
++ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
++ * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
++ * Copyright (C) 2004 Micrtronix Datacom Ltd.
++ *
++ * You can put anything here, but:
++ * LINUX_LOGO_COLORS has to be less than 224
++ * image size has to be 80x80
++ * values have to start from 0x20
++ * (i.e. RGB(linux_logo_red[0],
++ * linux_logo_green[0],
++ * linux_logo_blue[0]) is color 0x20)
++ * BW image has to be 80x80 as well, with MS bit
++ * on the left
++ * Serial_console ascii image can be any size,
++ * but should contain %s to display the version
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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/init.h>
++#include <linux/version.h>
++
++#define linux_logo_banner "Linux/NIOS2 version " UTS_RELEASE
++
++#define __HAVE_ARCH_LINUX_LOGO
++#define __HAVE_ARCH_LINUX_LOGO16
++
++#define LINUX_LOGO_COLORS 221
++
++#ifdef INCLUDE_LINUX_LOGO_DATA
++
++unsigned char linux_logo_red[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79,
++ 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7,
++ 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8,
++ 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6,
++ 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee,
++ 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c,
++ 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e,
++ 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c,
++ 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfe,
++ 0xf6, 0xec, 0xfe, 0xd2, 0xea, 0xf5, 0xf2, 0xf2,
++ 0xe9, 0xee, 0xf6, 0xf2, 0xee, 0xf6, 0xda, 0xd4,
++ 0xfa, 0xca, 0xf2, 0xf6, 0xfe, 0xf2, 0xda, 0xe4,
++ 0xf6, 0xdd, 0xf2, 0xee, 0xfa, 0xf0, 0x12, 0x4a,
++ 0xd6, 0xf2, 0x8e, 0xf2, 0xf6, 0xf6, 0xb5, 0xf1,
++ 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, 0x9a,
++ 0x2e, 0xd2, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62,
++ 0xda, 0xee, 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xe0,
++ 0xae, 0xbe, 0xce, 0xe2, 0xa3, 0x8e, 0x6d, 0x8e,
++ 0x32, 0xaf, 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82,
++ 0x7a, 0x82, 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86,
++ 0x6a, 0x52, 0x59, 0x64, 0x5e,
++};
++
++unsigned char linux_logo_green[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c,
++ 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae,
++ 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8,
++ 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda,
++ 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca,
++ 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76,
++ 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46,
++ 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b,
++ 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfa,
++ 0xea, 0xd7, 0xf6, 0xbc, 0xda, 0xde, 0xda, 0xe6,
++ 0xca, 0xd8, 0xea, 0xe0, 0xcc, 0xf2, 0xce, 0xb2,
++ 0xee, 0xa2, 0xd6, 0xe6, 0xf6, 0xd7, 0xc5, 0xb8,
++ 0xc6, 0xb9, 0xce, 0xde, 0xce, 0xc6, 0x0e, 0x36,
++ 0xae, 0xbe, 0x86, 0xba, 0xbe, 0xe6, 0x8e, 0xc4,
++ 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, 0x7a,
++ 0x20, 0xc6, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46,
++ 0xce, 0xd6, 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa6,
++ 0x87, 0x96, 0xa2, 0xd6, 0x85, 0x7a, 0x6a, 0x6e,
++ 0x22, 0x76, 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53,
++ 0x66, 0x62, 0x42, 0x50, 0x56, 0x42, 0x56, 0x56,
++ 0x56, 0x3e, 0x51, 0x52, 0x56,
++};
++
++unsigned char linux_logo_blue[] __initdata = {
++ 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22,
++ 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56,
++ 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65,
++ 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6,
++ 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6,
++ 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7,
++ 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08,
++ 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f,
++ 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e,
++ 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c,
++ 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f,
++ 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a,
++ 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e,
++ 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b,
++ 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c,
++ 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xea,
++ 0xb6, 0x7c, 0xda, 0x8e, 0xa6, 0x87, 0x66, 0xb6,
++ 0x81, 0x6a, 0xc6, 0x9a, 0x5b, 0xd2, 0xb6, 0x6a,
++ 0xca, 0x45, 0x92, 0xb2, 0xca, 0x52, 0x8a, 0x3e,
++ 0x2e, 0x66, 0x66, 0xae, 0x3e, 0x47, 0x06, 0x0e,
++ 0x52, 0x36, 0x6a, 0x0e, 0x0e, 0xbe, 0x2c, 0x0e,
++ 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, 0x2e,
++ 0x06, 0x9e, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06,
++ 0x9e, 0xae, 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x0a,
++ 0x32, 0x2e, 0x2a, 0xb2, 0x43, 0x48, 0x5f, 0x2e,
++ 0x06, 0x06, 0x07, 0x24, 0x06, 0x32, 0x06, 0x06,
++ 0x46, 0x2e, 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06,
++ 0x3a, 0x22, 0x42, 0x34, 0x42,
++};
++
++unsigned char linux_logo[] __initdata = {
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
++ 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++ 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d,
++ 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24,
++ 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c,
++ 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31,
++ 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34,
++ 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36,
++ 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22,
++ 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25,
++ 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22,
++ 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36,
++ 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36,
++ 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36,
++ 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36,
++ 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23,
++ 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21,
++ 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b,
++ 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26,
++ 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d,
++ 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32,
++ 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a,
++ 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b,
++ 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37,
++ 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58,
++ 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35,
++ 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
++ 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22,
++ 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67,
++ 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36,
++ 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e,
++ 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73,
++ 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78,
++ 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21,
++ 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79,
++ 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c,
++ 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24,
++ 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71,
++ 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36,
++ 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21,
++ 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89,
++ 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36,
++ 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21,
++ 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e,
++ 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23,
++ 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22,
++ 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63,
++ 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c,
++ 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51,
++ 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21,
++ 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97,
++ 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98,
++ 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39,
++ 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32,
++ 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50,
++ 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48,
++ 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23,
++ 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98,
++ 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50,
++ 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b,
++ 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b,
++ 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25,
++ 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33,
++ 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34,
++ 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52,
++ 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c,
++ 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c,
++ 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b,
++ 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93,
++ 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28,
++ 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99,
++ 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93,
++ 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36,
++ 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x99, 0x9f, 0x52, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47,
++ 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30,
++ 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c,
++ 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36,
++ 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48,
++ 0x47, 0x9f, 0x48, 0x48, 0x48, 0xa0, 0xa1, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36,
++ 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f,
++ 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36,
++ 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48,
++ 0xa3, 0xa4, 0x48, 0x48, 0x9f, 0xa5, 0xa6, 0x9f,
++ 0x48, 0x48, 0x48, 0xa2, 0xa7, 0x47, 0x48, 0x48,
++ 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23,
++ 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d,
++ 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25,
++ 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0xa8, 0xa1, 0x48, 0x48, 0x9f, 0xa9, 0xa6, 0x9f,
++ 0x48, 0x48, 0xaa, 0xa1, 0xa5, 0x9f, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30,
++ 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32,
++ 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a,
++ 0x36, 0x24, 0x4f, 0x48, 0x52, 0x52, 0x48, 0x48,
++ 0xab, 0xac, 0xa0, 0x48, 0xad, 0xa6, 0xa6, 0x9f,
++ 0x48, 0xa2, 0xa9, 0xa6, 0xa2, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30,
++ 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21,
++ 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25,
++ 0x36, 0x3a, 0x48, 0x48, 0xae, 0xaf, 0x48, 0x48,
++ 0xad, 0xac, 0xa1, 0x9f, 0xa2, 0xa9, 0xa9, 0xa2,
++ 0x48, 0xab, 0x78, 0xa7, 0x48, 0x48, 0x48, 0x48,
++ 0x9f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21,
++ 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36,
++ 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21,
++ 0x23, 0x43, 0x48, 0x48, 0xb0, 0xb1, 0xb2, 0x9f,
++ 0x48, 0xb3, 0xa5, 0xb3, 0xab, 0xa9, 0xa9, 0xb3,
++ 0xb4, 0xa9, 0xb5, 0xb0, 0x48, 0x48, 0xa0, 0xa5,
++ 0xa1, 0xad, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36,
++ 0x2e, 0x9b, 0x48, 0x48, 0x48, 0xb6, 0xb7, 0xa4,
++ 0xa2, 0xa7, 0xb5, 0x78, 0x6f, 0x6f, 0x6e, 0x6f,
++ 0xa9, 0xb5, 0xab, 0x48, 0x9f, 0xab, 0xa9, 0xa1,
++ 0xaa, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36,
++ 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36,
++ 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36,
++ 0x54, 0x48, 0x48, 0x48, 0x48, 0xa2, 0xa8, 0xa1,
++ 0xa5, 0xa6, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x6f, 0x78, 0xa5, 0xa0, 0xa0, 0x78, 0xa6, 0xa2,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36,
++ 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21,
++ 0x43, 0x48, 0x4b, 0xa2, 0x9f, 0x48, 0xa2, 0xa1,
++ 0xb8, 0x6e, 0x6e, 0xb5, 0x78, 0x6f, 0x78, 0x78,
++ 0x6e, 0x6f, 0x78, 0xb5, 0xa6, 0xa1, 0xa0, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21,
++ 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25,
++ 0x52, 0x48, 0xa3, 0xb1, 0xb6, 0xb3, 0xaa, 0xac,
++ 0x68, 0x68, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
++ 0x78, 0x6f, 0x6f, 0xb5, 0xa6, 0xb4, 0x48, 0x9f,
++ 0xb4, 0xb4, 0xa2, 0x9f, 0x48, 0x48, 0x4f, 0x21,
++ 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a,
++ 0x47, 0x48, 0xa2, 0xb6, 0xaf, 0xb9, 0xba, 0x68,
++ 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x78,
++ 0x6f, 0x6f, 0xa6, 0x6f, 0xb5, 0xa0, 0xaa, 0xa6,
++ 0xa6, 0xa9, 0xb2, 0xb3, 0x48, 0x48, 0x4c, 0x22,
++ 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39,
++ 0x9b, 0x48, 0x48, 0x48, 0xb0, 0xb0, 0xba, 0xb8,
++ 0x68, 0x68, 0x69, 0x78, 0x6f, 0xb5, 0x6f, 0xb5,
++ 0x78, 0x78, 0x78, 0x78, 0x78, 0xa5, 0xbb, 0xa9,
++ 0xa5, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23,
++ 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31,
++ 0x9b, 0x48, 0x48, 0x48, 0x48, 0x9f, 0xac, 0x68,
++ 0xbc, 0x6e, 0x6e, 0x6e, 0xb5, 0x6f, 0x6e, 0x6f,
++ 0x6f, 0x78, 0x78, 0xb5, 0xb5, 0xa5, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22,
++ 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d,
++ 0x9b, 0x48, 0x48, 0xb0, 0xaa, 0xb3, 0xbd, 0xb8,
++ 0xb8, 0x68, 0x6e, 0x6e, 0xb5, 0x6f, 0x78, 0x6e,
++ 0x78, 0x6f, 0x78, 0x78, 0xb5, 0xa9, 0xa2, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36,
++ 0x24, 0x27, 0xbe, 0x24, 0x25, 0x28, 0x21, 0x36,
++ 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25,
++ 0x39, 0x4d, 0xbf, 0x84, 0x81, 0x57, 0x21, 0x39,
++ 0x52, 0x48, 0x48, 0x62, 0xb1, 0xc0, 0xc1, 0xc1,
++ 0xb8, 0xb8, 0x68, 0xbc, 0x6e, 0x6e, 0x6e, 0x78,
++ 0x78, 0x78, 0x78, 0x6e, 0x78, 0xa9, 0xa0, 0xab,
++ 0xb3, 0xa2, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28,
++ 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30,
++ 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30,
++ 0x2d, 0xc2, 0x7a, 0xc3, 0xc4, 0xc4, 0x7f, 0x22,
++ 0x51, 0x52, 0x48, 0x48, 0xb0, 0xaa, 0xa8, 0xbd,
++ 0x68, 0xb8, 0xb8, 0x68, 0x68, 0x6e, 0x6e, 0x6f,
++ 0x6e, 0x6e, 0xb5, 0x6e, 0x78, 0xab, 0xab, 0xb5,
++ 0x78, 0xa6, 0xb3, 0xc5, 0xac, 0xac, 0xc6, 0x61,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32,
++ 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31,
++ 0x4d, 0x91, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0x5a,
++ 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0xb0, 0x64,
++ 0xc1, 0xb8, 0xb8, 0xb8, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6f, 0x71, 0x6f, 0x6f, 0xa6, 0xa0, 0x9f, 0xb4,
++ 0xb4, 0xa0, 0xa1, 0xb7, 0xc7, 0x69, 0x66, 0xc8,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25,
++ 0x83, 0xc9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a,
++ 0x60, 0x85, 0xca, 0xcb, 0xc4, 0xc4, 0xc4, 0x82,
++ 0x86, 0x36, 0x32, 0x3f, 0xa2, 0xa4, 0xa8, 0xa9,
++ 0xb8, 0xb8, 0xb8, 0xb8, 0x68, 0x6e, 0x6e, 0x6e,
++ 0x6e, 0x71, 0x6f, 0x71, 0xa6, 0xb4, 0x9f, 0x9f,
++ 0x48, 0x48, 0x48, 0xcc, 0xc3, 0xc7, 0xcd, 0xce,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57,
++ 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x23, 0x30, 0x31, 0xcf, 0x91, 0x7e, 0x90, 0x90,
++ 0x8b, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0x5d, 0xd0, 0x36, 0x24, 0xd1, 0xb1, 0xaf, 0xaa,
++ 0xba, 0xb8, 0x68, 0x68, 0x68, 0x71, 0x6e, 0x6e,
++ 0x6e, 0x6f, 0x6e, 0x78, 0xa1, 0xa9, 0xa1, 0xb0,
++ 0x9f, 0x9b, 0x99, 0xcc, 0x64, 0x5c, 0x8b, 0xd0,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d,
++ 0x82, 0x5c, 0xd2, 0x2a, 0x23, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x24, 0x2b, 0xcf, 0x8b, 0x5b, 0x76, 0x5b, 0x5b,
++ 0x7b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc7, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48,
++ 0xa2, 0xa8, 0xb7, 0xc1, 0xb8, 0x68, 0x68, 0xbc,
++ 0x68, 0x6e, 0xb5, 0xb4, 0xb4, 0xab, 0xb5, 0xa1,
++ 0xb0, 0x4f, 0x3f, 0xd3, 0x7b, 0x7b, 0x85, 0x80,
++ 0xbe, 0x36, 0x36, 0x36, 0x21, 0xd4, 0x7e, 0x7b,
++ 0x64, 0x64, 0xd5, 0x35, 0x24, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x31, 0xd6, 0x5b, 0x64, 0xc3, 0xc3, 0xcb,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x66, 0xd7, 0x36, 0x36, 0x36, 0x2c, 0x4b,
++ 0xd8, 0xd9, 0xb3, 0xa8, 0xbd, 0xbd, 0xbd, 0xbd,
++ 0xa9, 0xab, 0xb3, 0xa5, 0xa2, 0x9f, 0xa2, 0xa1,
++ 0x6a, 0x9a, 0x3f, 0xda, 0x76, 0x76, 0x7a, 0x63,
++ 0xdb, 0xdc, 0x86, 0xdc, 0xdd, 0x90, 0x5b, 0x64,
++ 0xc3, 0xc3, 0xde, 0x2d, 0x27, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc7, 0x83, 0xce, 0x36, 0x36, 0x36, 0x30,
++ 0xb1, 0xd9, 0x48, 0xa1, 0xb2, 0xb0, 0xb0, 0xb3,
++ 0xa2, 0x48, 0xa7, 0xbd, 0xa9, 0xa2, 0x48, 0x9f,
++ 0xaa, 0x9a, 0x3f, 0xb1, 0x5b, 0x7b, 0xdf, 0x85,
++ 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xc3, 0xc4,
++ 0xc4, 0xcb, 0x5d, 0xd5, 0x39, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe0, 0xdf, 0x64, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x88, 0x36, 0x36, 0x36, 0x36,
++ 0x2d, 0x9b, 0x48, 0xb9, 0xaf, 0xa2, 0xa2, 0xb9,
++ 0xa8, 0x9f, 0x48, 0xa7, 0xb7, 0xd9, 0x48, 0x48,
++ 0x9b, 0x45, 0x3f, 0xe1, 0x6d, 0x7b, 0xca, 0xdf,
++ 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc3, 0xe2, 0x37, 0x35, 0x26, 0x23,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2e, 0xe0, 0x7a, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc7, 0x72, 0x73, 0x36, 0x36, 0x36,
++ 0x24, 0x52, 0x48, 0xa3, 0xaf, 0x9f, 0x48, 0xb6,
++ 0xaf, 0xa2, 0x48, 0x9f, 0xe3, 0xd8, 0x48, 0x48,
++ 0x48, 0x46, 0x42, 0xd6, 0x7a, 0x7b, 0x64, 0x7b,
++ 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xc3, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0x64, 0xe2, 0x4d, 0x2c, 0x27,
++ 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x8b, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc7, 0x89, 0xbe, 0x36, 0x36,
++ 0x32, 0x47, 0x48, 0x4f, 0xa0, 0x48, 0x48, 0xe3,
++ 0x92, 0x9f, 0x48, 0x9f, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xc3, 0xcb,
++ 0xc3, 0x64, 0x64, 0xc3, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x5d, 0xe5, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x25, 0x31, 0xe4, 0x85, 0x7b, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x57, 0x27, 0x4d,
++ 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x99, 0x34, 0xbe, 0xdb, 0x7a, 0x7b, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xe4,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
++ 0x26, 0x2d, 0xe4, 0x85, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc7, 0x5f, 0x92, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44,
++ 0x35, 0x36, 0xce, 0xdd, 0x7a, 0x7b, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xc3, 0xe1,
++ 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x30, 0x2f, 0xd6, 0x8b, 0x7b, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x89, 0x45,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25,
++ 0x36, 0x36, 0x61, 0xdb, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0xdf, 0xe5,
++ 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xe6, 0x63, 0xdf, 0xc3, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x72, 0x81, 0xe7,
++ 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
++ 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36,
++ 0x36, 0x36, 0xe8, 0x8f, 0x6d, 0x64, 0xcb, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc3, 0xca, 0x8b, 0xcf, 0x2c,
++ 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x35, 0x96, 0x75, 0xca, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0x81, 0xdb,
++ 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b,
++ 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x73, 0xdb, 0x7a, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0x64, 0x76, 0x7a, 0x91, 0xd5, 0x31, 0x30,
++ 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24,
++ 0x39, 0x97, 0x75, 0xdf, 0x7b, 0x64, 0xc3, 0xc3,
++ 0xcb, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x7b, 0x7a, 0xe9,
++ 0xea, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30,
++ 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xdd, 0x8b, 0x7b, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x64, 0x64,
++ 0x76, 0x85, 0xe0, 0xd5, 0x34, 0x2b, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28,
++ 0x33, 0xeb, 0x63, 0x7e, 0x7a, 0x6d, 0xdf, 0x5b,
++ 0x76, 0x7b, 0x64, 0x64, 0xc3, 0xcb, 0xc4, 0xc4,
++ 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x76, 0x85, 0xdb,
++ 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xec, 0xdd, 0x75, 0x76, 0xc3, 0xc4,
++ 0xc4, 0xc4, 0xcb, 0xc3, 0x64, 0x76, 0xdf, 0x8b,
++ 0xd6, 0xd5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23,
++ 0x27, 0x31, 0xed, 0xeb, 0xdd, 0x74, 0x63, 0x90,
++ 0x7e, 0x75, 0x8b, 0x6d, 0xdf, 0x76, 0x64, 0xc3,
++ 0xcb, 0xcb, 0xcb, 0xcb, 0x64, 0x7a, 0x84, 0xee,
++ 0x79, 0xbe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x21, 0xea, 0xee, 0x63, 0x6d, 0x7b, 0x64,
++ 0xcb, 0xc3, 0x64, 0x7b, 0xdf, 0x75, 0x63, 0x96,
++ 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x28, 0x27, 0x35, 0x2d, 0x41, 0xd5, 0xe7, 0x8f,
++ 0xdb, 0xdd, 0xe9, 0x74, 0x84, 0x90, 0x85, 0x6d,
++ 0x5b, 0x7b, 0x7b, 0xca, 0x6d, 0x90, 0xdb, 0xef,
++ 0xec, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30,
++ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36,
++ 0x36, 0x21, 0xd4, 0x80, 0xe9, 0x7e, 0x6d, 0x76,
++ 0xca, 0x76, 0x6d, 0x85, 0x63, 0xdb, 0xd5, 0x34,
++ 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f,
++ 0x41, 0xf0, 0xf1, 0x6c, 0x80, 0xee, 0xdb, 0x74,
++ 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xef, 0x79,
++ 0xe8, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d,
++ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38,
++ 0x4d, 0x37, 0xf2, 0xf3, 0x8f, 0x74, 0x63, 0x7e,
++ 0x75, 0x7e, 0x63, 0xe9, 0x88, 0xe6, 0x31, 0x2a,
++ 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30,
++ 0x33, 0x39, 0x2e, 0x51, 0x41, 0xd2, 0x6c, 0xf3,
++ 0x80, 0xee, 0xee, 0xee, 0xf4, 0xf3, 0xd7, 0xf5,
++ 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27,
++ 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a,
++ 0x2b, 0x34, 0xf6, 0xec, 0xf7, 0x8f, 0xdd, 0xe9,
++ 0xe9, 0xdd, 0xee, 0x6c, 0x41, 0x39, 0x27, 0x28,
++ 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22,
++ 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41,
++ 0xf8, 0xd7, 0x79, 0x79, 0x79, 0xec, 0xf9, 0x51,
++ 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22,
++ 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23,
++ 0x24, 0x2a, 0x31, 0xfa, 0xea, 0x79, 0xf3, 0x80,
++ 0xf7, 0xdc, 0xfb, 0x2f, 0x35, 0x26, 0x23, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b,
++ 0x31, 0x2f, 0xf6, 0xfa, 0xfa, 0x2f, 0x2e, 0x33,
++ 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x21, 0x28, 0x27, 0x35, 0x34, 0xfa, 0xfa, 0xfa,
++ 0xfc, 0xf6, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28,
++ 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28,
++ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35,
++ 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21,
++ 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24,
++ 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++};
++
++unsigned char linux_logo16[1];
++
++#endif /* INCLUDE_LINUX_LOGO_DATA */
++
++#include <linux/linux_logo.h>
++
+--- linux/include/asm-nios2nommu/local.h
++++ linux/include/asm-nios2nommu/local.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_LOCAL_H
++#define __NIOS2NOMMU_LOCAL_H
++
++#include <asm-generic/local.h>
++
++#endif /* __NIOS2NOMMU_LOCAL_H */
+--- linux/include/asm-nios2nommu/mc146818rtc.h
++++ linux/include/asm-nios2nommu/mc146818rtc.h
+@@ -0,0 +1,29 @@
++/*
++ * Machine dependent access functions for RTC registers.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MC146818RTC_H
++#define _NIOS2_MC146818RTC_H
++
++/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
++
++#endif /* _NIOS2_MC146818RTC_H */
+--- linux/include/asm-nios2nommu/mman.h
++++ linux/include/asm-nios2nommu/mman.h
+@@ -0,0 +1,68 @@
++/*
++ * Copied from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_MMAN_H__
++#define __NIOS2_MMAN_H__
++
++#define PROT_READ 0x1 /* page can be read */
++#define PROT_WRITE 0x2 /* page can be written */
++#define PROT_EXEC 0x4 /* page can be executed */
++#define PROT_SEM 0x8 /* page may be used for atomic ops */
++#define PROT_NONE 0x0 /* page can not be accessed */
++#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
++#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
++
++#define MAP_SHARED 0x01 /* Share changes */
++#define MAP_PRIVATE 0x02 /* Changes are private */
++#define MAP_TYPE 0x0f /* Mask for type of mapping */
++#define MAP_FIXED 0x10 /* Interpret addr exactly */
++#define MAP_ANONYMOUS 0x20 /* don't use a file */
++
++#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
++#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
++#define MAP_LOCKED 0x2000 /* pages are locked */
++#define MAP_NORESERVE 0x4000 /* don't check for reservations */
++#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++#define MAP_NONBLOCK 0x10000 /* do not block on IO */
++
++#define MS_ASYNC 1 /* sync memory asynchronously */
++#define MS_INVALIDATE 2 /* invalidate the caches */
++#define MS_SYNC 4 /* synchronous memory sync */
++
++#define MCL_CURRENT 1 /* lock all current mappings */
++#define MCL_FUTURE 2 /* lock all future mappings */
++
++#define MADV_NORMAL 0x0 /* default page-in behavior */
++#define MADV_RANDOM 0x1 /* page-in minimum required */
++#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
++#define MADV_WILLNEED 0x3 /* pre-fault pages */
++#define MADV_DONTNEED 0x4 /* discard these pages */
++
++/* compatibility flags */
++#define MAP_ANON MAP_ANONYMOUS
++#define MAP_FILE 0
++
++#endif /* __NIOS2_MMAN_H__ */
++
+--- linux/include/asm-nios2nommu/mmu.h
++++ linux/include/asm-nios2nommu/mmu.h
+@@ -0,0 +1,47 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_H
++#define __NIOS2NOMMU_MMU_H
++
++/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
++
++struct mm_rblock_struct {
++ int size;
++ int refcount;
++ void *kblock;
++};
++
++struct mm_tblock_struct {
++ struct mm_rblock_struct *rblock;
++ struct mm_tblock_struct *next;
++};
++
++typedef struct {
++ struct mm_tblock_struct tblock;
++ unsigned long end_brk;
++} mm_context_t;
++
++#endif /* __NIOS2NOMMU_MMU_H */
+--- linux/include/asm-nios2nommu/mmu_context.h
++++ linux/include/asm-nios2nommu/mmu_context.h
+@@ -0,0 +1,58 @@
++/*
++ *
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2NOMMU_MMU_CONTEXT_H
++#define __NIOS2NOMMU_MMU_CONTEXT_H
++
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++}
++
++extern inline int
++init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++ // mm->context = virt_to_phys(mm->pgd);
++ return(0);
++}
++
++#define destroy_context(mm) do { } while(0)
++
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
++{
++}
++
++#define deactivate_mm(tsk,mm) do { } while (0)
++
++extern inline void activate_mm(struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++}
++
++#endif
+--- linux/include/asm-nios2nommu/module.h
++++ linux/include/asm-nios2nommu/module.h
+@@ -0,0 +1,36 @@
++#ifndef _NIOS2_MODULE_H
++#define _NIOS2_MODULE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/module.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct mod_arch_specific
++{
++};
++
++#define Elf_Shdr Elf32_Shdr
++#define Elf_Sym Elf32_Sym
++#define Elf_Ehdr Elf32_Ehdr
++
++#endif /* _NIOS_MODULE_H */
+--- linux/include/asm-nios2nommu/msgbuf.h
++++ linux/include/asm-nios2nommu/msgbuf.h
+@@ -0,0 +1,56 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_MSGBUF_H
++#define _NIOS2_MSGBUF_H
++
++/*
++ * The msqid64_ds structure for nios2 architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct msqid64_ds {
++ struct ipc64_perm msg_perm;
++ __kernel_time_t msg_stime; /* last msgsnd time */
++ unsigned long __unused1;
++ __kernel_time_t msg_rtime; /* last msgrcv time */
++ unsigned long __unused2;
++ __kernel_time_t msg_ctime; /* last change time */
++ unsigned long __unused3;
++ unsigned long msg_cbytes; /* current number of bytes on queue */
++ unsigned long msg_qnum; /* number of messages in queue */
++ unsigned long msg_qbytes; /* max number of bytes on queue */
++ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
++ __kernel_pid_t msg_lrpid; /* last receive pid */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#endif /* _NIOS2_MSGBUF_H */
++
+--- linux/include/asm-nios2nommu/namei.h
++++ linux/include/asm-nios2nommu/namei.h
+@@ -0,0 +1,36 @@
++/*
++ * linux/include/asm-nios/namei.h
++ * Moved from m68k version
++ * Included from linux/fs/namei.c
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 __NIOS2_NAMEI_H
++#define __NIOS2_NAMEI_H
++
++/* This dummy routine maybe changed to something useful
++ * for /usr/gnemul/ emulation stuff.
++ * Look at asm-sparc/namei.h for details.
++ */
++
++#define __emul_prefix() NULL
++
++#endif
+--- linux/include/asm-nios2nommu/ndma.h
++++ linux/include/asm-nios2nommu/ndma.h
+@@ -0,0 +1,64 @@
++#ifndef __NDMA_H__
++ #define __NDMA_H__
++
++ #ifndef __ASSEMBLY__
++
++// DMA Registers
++typedef volatile struct
++{
++ int np_dmastatus; // status register
++ int np_dmareadaddress; // read address
++ int np_dmawriteaddress; // write address
++ int np_dmalength; // length in bytes
++ int np_dmareserved1; // reserved
++ int np_dmareserved2; // reserved
++ int np_dmacontrol; // control register
++ int np_dmareserved3; // control register alternate
++} np_dma;
++
++// DMA Register Bits
++enum
++{
++ np_dmacontrol_byte_bit = 0, // Byte transaction
++ np_dmacontrol_hw_bit = 1, // Half-word transaction
++ np_dmacontrol_word_bit = 2, // Word transaction
++ np_dmacontrol_go_bit = 3, // enable execution
++ np_dmacontrol_i_en_bit = 4, // enable interrupt
++ np_dmacontrol_reen_bit = 5, // Enable read end-of-packet
++ np_dmacontrol_ween_bit = 6, // Enable write end-of-packet
++ np_dmacontrol_leen_bit = 7, // Enable length=0 transaction end
++ np_dmacontrol_rcon_bit = 8, // Read from a fixed address
++ np_dmacontrol_wcon_bit = 9, // Write to a fixed address
++ np_dmacontrol_doubleword_bit = 10, // Double-word transaction
++ np_dmacontrol_quadword_bit = 11, // Quad-word transaction
++
++ np_dmastatus_done_bit = 0, // 1 when done. Status write clears.
++ np_dmastatus_busy_bit = 1, // 1 when busy.
++ np_dmastatus_reop_bit = 2, // read-eop received
++ np_dmastatus_weop_bit = 3, // write-eop received
++ np_dmastatus_len_bit = 4, // requested length transacted
++
++ np_dmacontrol_byte_mask = (1 << 0), // Byte transaction
++ np_dmacontrol_hw_mask = (1 << 1), // Half-word transaction
++ np_dmacontrol_word_mask = (1 << 2), // Word transaction
++ np_dmacontrol_go_mask = (1 << 3), // enable execution
++ np_dmacontrol_i_en_mask = (1 << 4), // enable interrupt
++ np_dmacontrol_reen_mask = (1 << 5), // Enable read end-of-packet
++ np_dmacontrol_ween_mask = (1 << 6), // Enable write end-of-packet
++ np_dmacontrol_leen_mask = (1 << 7), // Enable length=0 transaction end
++ np_dmacontrol_rcon_mask = (1 << 8), // Read from a fixed address
++ np_dmacontrol_wcon_mask = (1 << 9), // Write to a fixed address
++ np_dmacontrol_doubleword_mask = (1 << 10), // Double-word transaction
++ np_dmacontrol_quadword_mask = (1 << 11), // Quad-word transaction
++
++ np_dmastatus_done_mask = (1 << 0), // 1 when done. Status write clears.
++ np_dmastatus_busy_mask = (1 << 1), // 1 when busy.
++ np_dmastatus_reop_mask = (1 << 2), // read-eop received
++ np_dmastatus_weop_mask = (1 << 3), // write-eop received
++ np_dmastatus_len_mask = (1 << 4), // requested length transacted
++};
++
++ #endif /* __ASSEMBLY__ */
++
++#endif
++/* End of File */
+--- linux/include/asm-nios2nommu/nios.h
++++ linux/include/asm-nios2nommu/nios.h
+@@ -0,0 +1,7 @@
++#ifndef __NIOS_H__
++#define __NIOS_H__
++
++#include "nios2_system.h"
++
++#endif
++
+--- linux/include/asm-nios2nommu/page.h
++++ linux/include/asm-nios2nommu/page.h
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_PAGE_H
++#define _NIOS2_PAGE_H
++
++/* copied from m68knommu arch */
++// #include <linux/config.h>
++
++/* PAGE_SHIFT determines the page size */
++
++#define PAGE_SHIFT (12)
++#define PAGE_SIZE (1UL << PAGE_SHIFT)
++#define PAGE_MASK (~(PAGE_SIZE-1))
++
++#ifdef __KERNEL__
++
++#include <asm/setup.h>
++
++#if PAGE_SHIFT < 13
++#define THREAD_SIZE (8192)
++#else
++#define THREAD_SIZE PAGE_SIZE
++#endif
++
++#ifndef __ASSEMBLY__
++
++#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
++#define free_user_page(page, addr) free_page(addr)
++
++#define clear_page(page) memset((page), 0, PAGE_SIZE)
++#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
++
++#define clear_user_page(page, vaddr, pg) clear_page(page)
++#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
++
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef struct { unsigned long pte; } pte_t;
++typedef struct { unsigned long pmd[16]; } pmd_t;
++typedef struct { unsigned long pgd; } pgd_t;
++typedef struct { unsigned long pgprot; } pgprot_t;
++
++#define pte_val(x) ((x).pte)
++#define pmd_val(x) ((&x)->pmd[0])
++#define pgd_val(x) ((x).pgd)
++#define pgprot_val(x) ((x).pgprot)
++
++#define __pte(x) ((pte_t) { (x) } )
++#define __pmd(x) ((pmd_t) { (x) } )
++#define __pgd(x) ((pgd_t) { (x) } )
++#define __pgprot(x) ((pgprot_t) { (x) } )
++
++/* to align the pointer to the (next) page boundary */
++#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
++
++/* Pure 2^n version of get_order */
++extern __inline__ int get_order(unsigned long size)
++{
++ int order;
++
++ size = (size-1) >> (PAGE_SHIFT-1);
++ order = -1;
++ do {
++ size >>= 1;
++ order++;
++ } while (size);
++ return order;
++}
++
++extern unsigned long memory_start;
++extern unsigned long memory_end;
++
++#endif /* !__ASSEMBLY__ */
++#include <asm/nios.h>
++#define PAGE_OFFSET ((int)(nasys_program_mem))
++
++#ifndef __ASSEMBLY__
++
++#define __pa(vaddr) virt_to_phys((void *)vaddr)
++#define __va(paddr) phys_to_virt((unsigned long)paddr)
++
++#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
++
++#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
++#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
++
++#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
++#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
++#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
++
++#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
++#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
++
++#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
++ ((void *)(kaddr) < (void *)memory_end))
++
++#ifdef CONFIG_NO_KERNEL_MSG
++#define BUG_PRINT()
++#else
++#define BUG_PRINT() printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__)
++#endif
++
++#ifdef na_cpu_oci_core
++#define BUG_PANIC() asm volatile ("break") /* drop to debugger */
++#else
++// #define BUG_PANIC() while(1)
++#define BUG_PANIC() panic("BUG!")
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_PAGE_H */
+--- linux/include/asm-nios2nommu/param.h
++++ linux/include/asm-nios2nommu/param.h
+@@ -0,0 +1,49 @@
++#ifndef _NIOS_PARAM_H
++#define _NIOS_PARAM_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/param.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifndef HZ
++#define HZ 100
++#endif
++
++#ifdef __KERNEL__
++#define USER_HZ HZ
++#define CLOCKS_PER_SEC (USER_HZ)
++#endif
++
++#define EXEC_PAGESIZE 4096
++
++#ifndef NGROUPS
++#define NGROUPS 32
++#endif
++
++#ifndef NOGROUP
++#define NOGROUP (-1)
++#endif
++
++#define MAXHOSTNAMELEN 64 /* max length of hostname */
++
++#endif
+--- linux/include/asm-nios2nommu/pci.h
++++ linux/include/asm-nios2nommu/pci.h
+@@ -0,0 +1,75 @@
++#ifndef _ASM_NIOS2NOMMU_PCI_H
++#define _ASM_NIOS2NOMMU_PCI_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pci.h
++ *
++ * Derived from asm-m68k/pci_m68k.h
++ * - m68k specific PCI declarations, by Wout Klaren.
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/scatterlist.h>
++
++struct pci_ops;
++
++/*
++ * Structure with hardware dependent information and functions of the
++ * PCI bus.
++ */
++
++struct pci_bus_info
++{
++ /*
++ * Resources of the PCI bus.
++ */
++
++ struct resource mem_space;
++ struct resource io_space;
++
++ /*
++ * System dependent functions.
++ */
++
++ struct pci_ops *m68k_pci_ops;
++
++ void (*fixup)(int pci_modify);
++ void (*conf_device)(struct pci_dev *dev);
++};
++
++#define pcibios_assign_all_busses() 0
++
++extern inline void pcibios_set_master(struct pci_dev *dev)
++{
++ /* No special bus mastering setup handling */
++}
++
++extern inline void pcibios_penalize_isa_irq(int irq)
++{
++ /* We don't do dynamic PCI IRQ allocation */
++}
++
++/* The PCI address space does equal the physical memory
++ * address space. The networking and block device layers use
++ * this boolean for bounce buffer decisions.
++ */
++#define PCI_DMA_BUS_IS_PHYS (1)
++
++#endif /* _ASM_NIOS2NOMMU_PCI_H */
+--- linux/include/asm-nios2nommu/percpu.h
++++ linux/include/asm-nios2nommu/percpu.h
+@@ -0,0 +1,30 @@
++#ifndef __ARCH_NIOS2NOMMU_PERCPU__
++#define __ARCH_NIOS2NOMMU_PERCPU__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/percpu.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/percpu.h>
++
++#endif /* __ARCH_NIOS2NOMMU_PERCPU__ */
+--- linux/include/asm-nios2nommu/pgalloc.h
++++ linux/include/asm-nios2nommu/pgalloc.h
+@@ -0,0 +1,32 @@
++#ifndef _NIOS2NOMMU_PGALLOC_H
++#define _NIOS2NOMMU_PGALLOC_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgalloc.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/setup.h>
++
++#define check_pgt_cache() do { } while (0)
++
++#endif /* _NIOS2NOMMU_PGALLOC_H */
+--- linux/include/asm-nios2nommu/pgtable.h
++++ linux/include/asm-nios2nommu/pgtable.h
+@@ -0,0 +1,100 @@
++#ifndef _NIOS_PGTABLE_H
++#define _NIOS_PGTABLE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/pgtable.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++//vic - this bit copied from m68knommu version
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/io.h>
++
++typedef pte_t *pte_addr_t;
++
++#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
++#define pgd_none(pgd) (0)
++#define pgd_bad(pgd) (0)
++#define pgd_clear(pgdp)
++#define kern_addr_valid(addr) (1)
++#define pmd_offset(a, b) ((void *)0)
++
++#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
++#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
++//vic - this bit copied from m68knommu version
++
++extern void paging_init(void);
++#define swapper_pg_dir ((pgd_t *) 0)
++
++#define __swp_type(x) (0)
++#define __swp_offset(x) (0)
++#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
++#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
++#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
++
++static inline int pte_file(pte_t pte) { return 0; }
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++#define ZERO_PAGE(vaddr) (virt_to_page(0))
++
++extern unsigned int kobjsize(const void *objp);
++
++/*
++ * No page table caches to initialise
++ */
++#define pgtable_cache_init() do { } while (0)
++
++extern inline void flush_cache_mm(struct mm_struct *mm)
++{
++}
++
++extern inline void flush_cache_range(struct mm_struct *mm,
++ unsigned long start,
++ unsigned long end)
++{
++}
++
++/* Push the page at kernel virtual address and clear the icache */
++extern inline void flush_page_to_ram (unsigned long address)
++{
++}
++
++/* Push n pages at kernel virtual address and clear the icache */
++extern inline void flush_pages_to_ram (unsigned long address, int n)
++{
++}
++
++/*
++ * All 32bit addresses are effectively valid for vmalloc...
++ * Sort of meaningless for non-VM targets.
++ */
++#define VMALLOC_START 0
++#define VMALLOC_END 0xffffffff
++
++#endif /* _NIOS_PGTABLE_H */
+--- linux/include/asm-nios2nommu/pio_struct.h
++++ linux/include/asm-nios2nommu/pio_struct.h
+@@ -0,0 +1,14 @@
++// PIO Peripheral
++
++// PIO Registers
++typedef volatile struct
++ {
++ int np_piodata; // read/write, up to 32 bits
++ int np_piodirection; // write/readable, up to 32 bits, 1->output bit
++ int np_piointerruptmask; // write/readable, up to 32 bits, 1->enable interrupt
++ int np_pioedgecapture; // read, up to 32 bits, cleared by any write
++ } np_pio;
++
++// PIO Routines
++void nr_pio_showhex(int value); // shows low byte on pio named na_seven_seg_pio
++
+--- linux/include/asm-nios2nommu/poll.h
++++ linux/include/asm-nios2nommu/poll.h
+@@ -0,0 +1,46 @@
++#ifndef __NIOS2_POLL_H
++#define __NIOS2_POLL_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/poll.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define POLLIN 1
++#define POLLPRI 2
++#define POLLOUT 4
++#define POLLERR 8
++#define POLLHUP 16
++#define POLLNVAL 32
++#define POLLRDNORM 64
++#define POLLWRNORM POLLOUT
++#define POLLRDBAND 128
++#define POLLWRBAND 256
++#define POLLMSG 0x0400
++
++struct pollfd {
++ int fd;
++ short events;
++ short revents;
++};
++
++#endif
+--- linux/include/asm-nios2nommu/posix_types.h
++++ linux/include/asm-nios2nommu/posix_types.h
+@@ -0,0 +1,89 @@
++#ifndef __ARCH_NIOS2_POSIX_TYPES_H
++#define __ARCH_NIOS2_POSIX_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/posix_types.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned short __kernel_uid_t;
++typedef unsigned short __kernel_gid_t;
++typedef unsigned int __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__KERNEL__) || defined(__USE_ALL)
++ int val[2];
++#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++ int __val[2];
++#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
++} __kernel_fsid_t;
++
++#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
++
++#undef __FD_SET
++#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
++
++#undef __FD_CLR
++#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
++
++#undef __FD_ISSET
++#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
++
++#undef __FD_ZERO
++#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
++
++#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
++
++#endif
+--- linux/include/asm-nios2nommu/preem_latency.h
++++ linux/include/asm-nios2nommu/preem_latency.h
+@@ -0,0 +1,39 @@
++#ifndef _ASM_PREEM_LATENCY_H
++#define _ASM_PREEM_LATENCY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/preem_latency.h
++ *
++ * timing support for preempt-stats patch
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++#define readclock(low) \
++do {\
++ *(volatile unsigned long *)na_Counter_64_bit=1; \
++ low=*(volatile unsigned long *)na_Counter_64_bit; \
++} while (0)
++#define readclock_init()
++
++#endif /* _ASM_PREEM_LATENCY_H */
+--- linux/include/asm-nios2nommu/processor.h
++++ linux/include/asm-nios2nommu/processor.h
+@@ -0,0 +1,148 @@
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/processor.h
++ *
++ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2001 Ken Hill (khill@microtronix.com)
++ * Vic Phillips (vic@microtronix.com)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * hacked from:
++ * include/asm-sparc/processor.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ * Nov/02/2003 dgt Fix task_size
++ *
++ ---------------------------------------------------------------------*/
++
++#ifndef __ASM_NIOS_PROCESSOR_H
++#define __ASM_NIOS_PROCESSOR_H
++
++#define NIOS2_FLAG_KTHREAD 0x00000001 /* task is a kernel thread */
++#define NIOS2_FLAG_COPROC 0x00000002 /* Thread used coprocess */
++#define NIOS2_FLAG_DEBUG 0x00000004 /* task is being debugged */
++
++#define NIOS2_OP_NOP 0x1883a
++#define NIOS2_OP_BREAK 0x3da03a
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l;})
++
++#include <linux/a.out.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/signal.h>
++#include <asm/segment.h>
++#include <asm/current.h>
++#include <asm/system.h> /* for get_hi_limit */
++
++/*
++ * Bus types
++ */
++#define EISA_bus 0
++#define EISA_bus__is_a_macro /* for versions in ksyms.c */
++#define MCA_bus 0
++#define MCA_bus__is_a_macro /* for versions in ksyms.c */
++
++/*
++ * The nios has no problems with write protection
++ */
++#define wp_works_ok 1
++#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
++
++/* Whee, this is STACK_TOP and the lowest kernel address too... */
++#if 0
++#define KERNBASE 0x00000000 /* First address the kernel will eventually be */
++#define TASK_SIZE (KERNBASE)
++#define MAX_USER_ADDR TASK_SIZE
++#define MMAP_SEARCH_START (TASK_SIZE/3)
++#endif
++
++#define TASK_SIZE ((unsigned int) nasys_program_mem_end) //...this is better...
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
++ * space during mmap's. We won't be using it
++ */
++#define TASK_UNMAPPED_BASE 0
++
++/* The Nios processor specific thread struct. */
++struct thread_struct {
++ struct pt_regs *kregs;
++
++ /* For signal handling */
++ unsigned long sig_address;
++ unsigned long sig_desc;
++
++ /* Context switch saved kernel state. */
++ unsigned long ksp;
++ unsigned long kpsr;
++ unsigned long kesr;
++
++ /* Flags are defined below */
++
++ unsigned long flags;
++ int current_ds;
++ struct exec core_exec; /* just what it says. */
++};
++
++#define INIT_MMAP { &init_mm, (0), (0), \
++ __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC }
++
++#define INIT_THREAD { \
++ .kregs = 0, \
++ .sig_address = 0, \
++ .sig_desc = 0, \
++ .ksp = 0, \
++ .kpsr = 0, \
++ .kesr = PS_S, \
++ .flags = NIOS2_FLAG_KTHREAD, \
++ .current_ds = __KERNEL_DS, \
++ .core_exec = INIT_EXEC \
++}
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++extern unsigned long thread_saved_pc(struct task_struct *t);
++
++extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++#define prepare_to_copy(tsk) do { } while (0)
++
++extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define KSTK_EIP(tsk) ((tsk)->thread.kregs->ea)
++#define KSTK_ESP(tsk) ((tsk)->thread.kregs->sp)
++
++#ifdef __KERNEL__
++/* Allocation and freeing of basic task resources. */
++
++//;dgt2;#define alloc_task_struct() ((struct task_struct *) xx..see..linux..fork..xx __get_free_pages(GFP_KERNEL,1))
++//;dgt2;#define get_task_struct(tsk) xx..see..linux..sched.h...atomic_inc(&mem_map[MAP_NR(tsk)].count)
++
++#endif
++
++#define cpu_relax() do { } while (0)
++#endif /* __ASSEMBLY__ */
++#endif /* __ASM_NIOS_PROCESSOR_H */
+--- linux/include/asm-nios2nommu/ptrace.h
++++ linux/include/asm-nios2nommu/ptrace.h
+@@ -0,0 +1,141 @@
++/*
++ * Taken from the m68k port.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_PTRACE_H
++#define _NIOS2NOMMU_PTRACE_H
++
++#ifndef __ASSEMBLY__
++
++#define PTR_R0 0
++#define PTR_R1 1
++#define PTR_R2 2
++#define PTR_R3 3
++#define PTR_R4 4
++#define PTR_R5 5
++#define PTR_R6 6
++#define PTR_R7 7
++#define PTR_R8 8
++#define PTR_R9 9
++#define PTR_R10 10
++#define PTR_R11 11
++#define PTR_R12 12
++#define PTR_R13 13
++#define PTR_R14 14
++#define PTR_R15 15
++#define PTR_R16 16
++#define PTR_R17 17
++#define PTR_R18 18
++#define PTR_R19 19
++#define PTR_R20 20
++#define PTR_R21 21
++#define PTR_R22 22
++#define PTR_R23 23
++#define PTR_R24 24
++#define PTR_R25 25
++#define PTR_GP 26
++#define PTR_SP 27
++#define PTR_FP 28
++#define PTR_EA 29
++#define PTR_BA 30
++#define PTR_RA 31
++#define PTR_STATUS 32
++#define PTR_ESTATUS 33
++#define PTR_BSTATUS 34
++#define PTR_IENABLE 35
++#define PTR_IPENDING 36
++
++/* this struct defines the way the registers are stored on the
++ stack during a system call.
++
++ There is a fake_regs in setup.c that has to match pt_regs.*/
++
++struct pt_regs {
++ unsigned long r8;
++ unsigned long r9;
++ unsigned long r10;
++ unsigned long r11;
++ unsigned long r12;
++ unsigned long r13;
++ unsigned long r14;
++ unsigned long r15;
++ unsigned long r1;
++ unsigned long r2;
++ unsigned long r3;
++ unsigned long r4;
++ unsigned long r5;
++ unsigned long r6;
++ unsigned long r7;
++ unsigned long orig_r2;
++ unsigned long ra;
++ unsigned long fp;
++ unsigned long sp;
++ unsigned long gp;
++ unsigned long estatus;
++ unsigned long status_extension;
++ unsigned long ea;
++};
++
++
++/*
++ * This is the extended stack used by signal handlers and the context
++ * switcher: it's pushed after the normal "struct pt_regs".
++ */
++struct switch_stack {
++ unsigned long r16;
++ unsigned long r17;
++ unsigned long r18;
++ unsigned long r19;
++ unsigned long r20;
++ unsigned long r21;
++ unsigned long r22;
++ unsigned long r23;
++ unsigned long fp;
++ unsigned long gp;
++ unsigned long ra;
++};
++
++/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
++#define PTRACE_GETREGS 12
++#define PTRACE_SETREGS 13
++#ifdef CONFIG_FPU
++#define PTRACE_GETFPREGS 14
++#define PTRACE_SETFPREGS 15
++#endif
++
++#ifdef __KERNEL__
++
++#ifndef PS_S
++#define PS_S (0x00000001)
++#endif
++#ifndef PS_T
++#define PS_T (0x00000002)
++#endif
++
++#define user_mode(regs) (!((regs)->status_extension & PS_S))
++#define instruction_pointer(regs) ((regs)->ra)
++#define profile_pc(regs) instruction_pointer(regs)
++extern void show_regs(struct pt_regs *);
++
++#endif /* __KERNEL__ */
++#endif /* __ASSEMBLY__ */
++#endif /* _NIOS2NOMMU_PTRACE_H */
+--- linux/include/asm-nios2nommu/resource.h
++++ linux/include/asm-nios2nommu/resource.h
+@@ -0,0 +1,73 @@
++#ifndef _NIOS2NOMMU_RESOURCE_H
++#define _NIOS2NOMMU_RESOURCE_H
++
++/*--------------------------------------------------------------------
++ *
++ * Resource limits
++ *
++ * include/asm-nios2nommu/resource.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define RLIMIT_CPU 0 /* CPU time in ms */
++#define RLIMIT_FSIZE 1 /* Maximum filesize */
++#define RLIMIT_DATA 2 /* max data size */
++#define RLIMIT_STACK 3 /* max stack size */
++#define RLIMIT_CORE 4 /* max core file size */
++#define RLIMIT_RSS 5 /* max resident set size */
++#define RLIMIT_NPROC 6 /* max number of processes */
++#define RLIMIT_NOFILE 7 /* max number of open files */
++#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
++#define RLIMIT_AS 9 /* address space limit */
++#define RLIMIT_LOCKS 10 /* maximum file locks held */
++#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
++#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
++
++#define RLIM_NLIMITS 13
++
++/*
++ * SuS says limits have to be unsigned.
++ * Which makes a ton more sense anyway.
++ */
++#define RLIM_INFINITY (~0UL)
++
++#ifdef __KERNEL__
++
++#define INIT_RLIMITS \
++{ \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { _STK_LIM, RLIM_INFINITY }, \
++ { 0, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { 0, 0 }, \
++ { INR_OPEN, INR_OPEN }, \
++ { MLOCK_LIMIT, MLOCK_LIMIT }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { RLIM_INFINITY, RLIM_INFINITY }, \
++ { MAX_SIGPENDING, MAX_SIGPENDING }, \
++ { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
++}
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2NOMMU_RESOURCE_H */
+--- linux/include/asm-nios2nommu/rmap.h
++++ linux/include/asm-nios2nommu/rmap.h
+@@ -0,0 +1,2 @@
++/* Do not need anything here */
++
+--- linux/include/asm-nios2nommu/scatterlist.h
++++ linux/include/asm-nios2nommu/scatterlist.h
+@@ -0,0 +1,40 @@
++#ifndef _NIOS2NOMMU_SCATTERLIST_H
++#define _NIOS2NOMMU_SCATTERLIST_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/scatterlist.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct scatterlist {
++ struct page *page;
++ unsigned int offset;
++ dma_addr_t dma_address;
++ unsigned int length;
++};
++
++#define sg_dma_address(sg) ((sg)->dma_address)
++#define sg_dma_len(sg) ((sg)->length)
++
++#define ISA_DMA_THRESHOLD (0xffffffff)
++
++#endif /* !(_NIOS2NOMMU_SCATTERLIST_H) */
+--- linux/include/asm-nios2nommu/sections.h
++++ linux/include/asm-nios2nommu/sections.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_SECTIONS_H
++#define _NIOS2NOMMU_SECTIONS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sections.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/sections.h>
++
++#endif /* _NIOS2NOMMU_SECTIONS_H */
+--- linux/include/asm-nios2nommu/segment.h
++++ linux/include/asm-nios2nommu/segment.h
+@@ -0,0 +1,75 @@
++#ifndef _NIOS2NOMMU_SEGMENT_H
++#define _NIOS2NOMMU_SEGMENT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/segment.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* define constants */
++/* Address spaces (FC0-FC2) */
++#define USER_DATA (1)
++#ifndef __USER_DS
++#define __USER_DS (USER_DATA)
++#endif
++#define USER_PROGRAM (2)
++#define SUPER_DATA (5)
++#ifndef __KERNEL_DS
++#define __KERNEL_DS (SUPER_DATA)
++#endif
++#define SUPER_PROGRAM (6)
++#define CPU_SPACE (7)
++
++#ifndef __ASSEMBLY__
++
++typedef struct {
++ unsigned long seg;
++} mm_segment_t;
++
++#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
++#define USER_DS MAKE_MM_SEG(__USER_DS)
++#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
++
++/*
++ * Get/set the SFC/DFC registers for MOVES instructions
++ */
++
++static inline mm_segment_t get_fs(void)
++{
++ return USER_DS;
++}
++
++static inline mm_segment_t get_ds(void)
++{
++ /* return the supervisor data space code */
++ return KERNEL_DS;
++}
++
++static inline void set_fs(mm_segment_t val)
++{
++}
++
++#define segment_eq(a,b) ((a).seg == (b).seg)
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _NIOS2NOMMU_SEGMENT_H */
+--- linux/include/asm-nios2nommu/semaphore-helper.h
++++ linux/include/asm-nios2nommu/semaphore-helper.h
+@@ -0,0 +1,101 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_HELPER_H
++#define _NIOS2NOMMU_SEMAPHORE_HELPER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * SMP- and interrupt-safe semaphores helper functions.
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++// #include <linux/config.h>
++
++/*
++ * These two _must_ execute atomically wrt each other.
++ */
++static inline void wake_one_more(struct semaphore * sem)
++{
++ atomic_inc(&sem->waking);
++}
++
++static inline int waking_non_zero(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_interruptible:
++ * 1 got the lock
++ * 0 go to sleep
++ * -EINTR interrupted
++ */
++static inline int waking_non_zero_interruptible(struct semaphore *sem,
++ struct task_struct *tsk)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 0;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 1;
++ } else if (signal_pending(tsk)) {
++ atomic_inc(&sem->count);
++ ret = -EINTR;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_trylock:
++ * 1 failed to lock
++ * 0 got the lock
++ */
++static inline int waking_non_zero_trylock(struct semaphore *sem)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ ret = 1;
++ if (atomic_read(&sem->waking) > 0) {
++ atomic_dec(&sem->waking);
++ ret = 0;
++ } else
++ atomic_inc(&sem->count);
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++#endif
+--- linux/include/asm-nios2nommu/semaphore.h
++++ linux/include/asm-nios2nommu/semaphore.h
+@@ -0,0 +1,155 @@
++#ifndef _NIOS2NOMMU_SEMAPHORE_H
++#define _NIOS2NOMMU_SEMAPHORE_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/semaphore.h
++ *
++ * Interrupt-safe semaphores..
++ *
++ * Derived from M68knommu
++ *
++ * (C) Copyright 1996 Linus Torvalds
++ * m68k version by Andreas Schwab
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define RW_LOCK_BIAS 0x01000000
++
++#ifndef __ASSEMBLY__
++
++#include <linux/linkage.h>
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++
++#include <asm/system.h>
++#include <asm/atomic.h>
++
++struct semaphore {
++ atomic_t count;
++ atomic_t waking;
++ wait_queue_head_t wait;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n) \
++{ \
++ .count = ATOMIC_INIT(n), \
++ .waking = ATOMIC_INIT(0), \
++ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
++}
++
++#define __MUTEX_INITIALIZER(name) \
++ __SEMAPHORE_INITIALIZER(name,1)
++
++#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
++ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
++
++#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
++#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
++
++extern inline void sema_init (struct semaphore *sem, int val)
++{
++ *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
++}
++
++static inline void init_MUTEX (struct semaphore *sem)
++{
++ sema_init(sem, 1);
++}
++
++static inline void init_MUTEX_LOCKED (struct semaphore *sem)
++{
++ sema_init(sem, 0);
++}
++
++asmlinkage void __down(struct semaphore * sem);
++asmlinkage int __down_interruptible(struct semaphore * sem);
++asmlinkage int __down_trylock(struct semaphore * sem);
++asmlinkage void __up(struct semaphore * sem);
++
++asmlinkage void __down_failed(void /* special register calling convention */);
++asmlinkage int __down_failed_interruptible(void /* params in registers */);
++asmlinkage int __down_failed_trylock(void /* params in registers */);
++asmlinkage void __up_wakeup(void /* special register calling convention */);
++
++extern spinlock_t semaphore_wake_lock;
++
++/*
++ * This is ugly, but we want the default case to fall through.
++ * "down_failed" is a special asm handler that calls the C
++ * routine that actually waits.
++ */
++extern inline void down(struct semaphore * sem)
++{
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if (atomic_dec_return(&sem->count) < 0)
++ __down(sem);
++ #endif
++}
++
++extern inline int down_interruptible(struct semaphore * sem)
++{
++ int ret = 0;
++
++
++ might_sleep();
++
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ if(atomic_dec_return(&sem->count) < 0)
++ ret = __down_interruptible(sem);
++ return ret;
++ #endif
++}
++
++extern inline int down_trylock(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "decrement memory"....
++ #else
++ int ret = 0;
++
++ if (atomic_dec_return (&sem->count) < 0)
++ ret = __down_trylock(sem);
++ return ret;
++ #endif
++}
++
++/*
++ * Note! This is subtle. We jump to wake people up only if
++ * the semaphore was negative (== somebody was waiting on it).
++ * The default case (no contention) will result in NO
++ * jumps for both down() and up().
++ */
++extern inline void up(struct semaphore * sem)
++{
++ #if 0
++ ...Nios2 has no atomic "increment memory"....
++ #else
++ if (atomic_inc_return(&sem->count) <= 0)
++ __up(sem);
++ #endif
++}
++
++#endif /* __ASSEMBLY__ */
++
++#endif
+--- linux/include/asm-nios2nommu/sembuf.h
++++ linux/include/asm-nios2nommu/sembuf.h
+@@ -0,0 +1,48 @@
++#ifndef _NIOS_SEMBUF_H
++#define _NIOS_SEMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sembuf.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct semid64_ds {
++ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
++ __kernel_time_t sem_otime; /* last semop time */
++ unsigned long __unused1;
++ __kernel_time_t sem_ctime; /* last change time */
++ unsigned long __unused2;
++ unsigned long sem_nsems; /* no. of semaphores in array */
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SEMBUF_H */
+--- linux/include/asm-nios2nommu/setup.h
++++ linux/include/asm-nios2nommu/setup.h
+@@ -0,0 +1,31 @@
++/* Copied from i386 port.
++ * Just a place holder. We don't want to have to test x86 before
++ * we include stuff
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SETUP_H
++#define _NIOS2_SETUP_H
++
++#define COMMAND_LINE_SIZE 512
++
++#endif /* _NIOS2_SETUP_H */
+--- linux/include/asm-nios2nommu/shmbuf.h
++++ linux/include/asm-nios2nommu/shmbuf.h
+@@ -0,0 +1,64 @@
++#ifndef _NIOS_SHMBUF_H
++#define _NIOS_SHMBUF_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmbuf.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/* Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct shmid64_ds {
++ struct ipc64_perm shm_perm; /* operation perms */
++ size_t shm_segsz; /* size of segment (bytes) */
++ __kernel_time_t shm_atime; /* last attach time */
++ unsigned long __unused1;
++ __kernel_time_t shm_dtime; /* last detach time */
++ unsigned long __unused2;
++ __kernel_time_t shm_ctime; /* last change time */
++ unsigned long __unused3;
++ __kernel_pid_t shm_cpid; /* pid of creator */
++ __kernel_pid_t shm_lpid; /* pid of last operator */
++ unsigned long shm_nattch; /* no. of current attaches */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++struct shminfo64 {
++ unsigned long shmmax;
++ unsigned long shmmin;
++ unsigned long shmmni;
++ unsigned long shmseg;
++ unsigned long shmall;
++ unsigned long __unused1;
++ unsigned long __unused2;
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _NIOS_SHMBUF_H */
+--- linux/include/asm-nios2nommu/shmparam.h
++++ linux/include/asm-nios2nommu/shmparam.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS2NOMMU_SHMPARAM_H__
++#define __NIOS2NOMMU_SHMPARAM_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/shmparam.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
++
++#endif /* __NIOS2NOMMU_SHMPARAM_H__ */
+--- linux/include/asm-nios2nommu/sigcontext.h
++++ linux/include/asm-nios2nommu/sigcontext.h
+@@ -0,0 +1,35 @@
++/*
++ * Taken from the m68knommu.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_NIOS2NOMMU_SIGCONTEXT_H
++#define _ASM_NIOS2NOMMU_SIGCONTEXT_H
++
++#include <asm/ptrace.h>
++
++struct sigcontext {
++ struct pt_regs regs;
++ unsigned long sc_mask; /* old sigmask */
++};
++
++#endif
+--- linux/include/asm-nios2nommu/siginfo.h
++++ linux/include/asm-nios2nommu/siginfo.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SIGINFO_H
++#define _NIOS2NOMMU_SIGINFO_H
++
++#include <asm-generic/siginfo.h>
++
++#endif
+--- linux/include/asm-nios2nommu/signal.h
++++ linux/include/asm-nios2nommu/signal.h
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_SIGNAL_H
++#define _NIOS2_SIGNAL_H
++
++#include <linux/types.h>
++
++/* Avoid too many header ordering problems. */
++struct siginfo;
++
++#ifdef __KERNEL__
++/* Most things should be clean enough to redefine this at will, if care
++ is taken to make libc match. */
++
++#define _NSIG 64
++#define _NSIG_BPW 32
++#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
++
++typedef unsigned long old_sigset_t; /* at least 32 bits */
++
++typedef struct {
++ unsigned long sig[_NSIG_WORDS];
++} sigset_t;
++
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++#define NSIG 32
++typedef unsigned long sigset_t;
++
++#endif /* __KERNEL__ */
++
++#define SIGHUP 1
++#define SIGINT 2
++#define SIGQUIT 3
++#define SIGILL 4
++#define SIGTRAP 5
++#define SIGABRT 6
++#define SIGIOT 6
++#define SIGBUS 7
++#define SIGFPE 8
++#define SIGKILL 9
++#define SIGUSR1 10
++#define SIGSEGV 11
++#define SIGUSR2 12
++#define SIGPIPE 13
++#define SIGALRM 14
++#define SIGTERM 15
++#define SIGSTKFLT 16
++#define SIGCHLD 17
++#define SIGCONT 18
++#define SIGSTOP 19
++#define SIGTSTP 20
++#define SIGTTIN 21
++#define SIGTTOU 22
++#define SIGURG 23
++#define SIGXCPU 24
++#define SIGXFSZ 25
++#define SIGVTALRM 26
++#define SIGPROF 27
++#define SIGWINCH 28
++#define SIGIO 29
++#define SIGPOLL SIGIO
++/*
++#define SIGLOST 29
++*/
++#define SIGPWR 30
++#define SIGSYS 31
++#define SIGUNUSED 31
++
++/* These should not be considered constants from userland. */
++#define SIGRTMIN 32
++#define SIGRTMAX _NSIG-1
++
++/*
++ * SA_FLAGS values:
++ *
++ * SA_ONSTACK indicates that a registered stack_t will be used.
++ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
++ * SA_RESTART flag to get restarting signals (which were the default long ago)
++ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
++ * SA_RESETHAND clears the handler when the signal is delivered.
++ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
++ * SA_NODEFER prevents the current signal from being masked in the handler.
++ *
++ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
++ * Unix names RESETHAND and NODEFER respectively.
++ */
++#define SA_NOCLDSTOP 0x00000001
++#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
++#define SA_SIGINFO 0x00000004
++#define SA_ONSTACK 0x08000000
++#define SA_RESTART 0x10000000
++#define SA_NODEFER 0x40000000
++#define SA_RESETHAND 0x80000000
++
++#define SA_NOMASK SA_NODEFER
++#define SA_ONESHOT SA_RESETHAND
++#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
++
++#define SA_RESTORER 0x04000000
++
++/*
++ * sigaltstack controls
++ */
++#define SS_ONSTACK 1
++#define SS_DISABLE 2
++
++#define MINSIGSTKSZ 2048
++#define SIGSTKSZ 8192
++
++#ifdef __KERNEL__
++/*
++ * These values of sa_flags are used only by the kernel as part of the
++ * irq handling routines.
++ *
++ * SA_INTERRUPT is also used by the irq handling routines.
++ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
++ */
++#define SA_PROBE SA_ONESHOT
++#define SA_SAMPLE_RANDOM SA_RESTART
++#define SA_SHIRQ 0x04000000
++#endif
++
++#define SIG_BLOCK 0 /* for blocking signals */
++#define SIG_UNBLOCK 1 /* for unblocking signals */
++#define SIG_SETMASK 2 /* for setting the signal mask */
++
++/* Type of a signal handler. */
++typedef void (*__sighandler_t)(int);
++
++#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
++#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
++#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
++
++#ifdef __KERNEL__
++struct old_sigaction {
++ __sighandler_t sa_handler;
++ old_sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++struct sigaction {
++ __sighandler_t sa_handler;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++ sigset_t sa_mask; /* mask last for extensibility */
++};
++
++struct k_sigaction {
++ struct sigaction sa;
++};
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++struct sigaction {
++ union {
++ __sighandler_t _sa_handler;
++ void (*_sa_sigaction)(int, struct siginfo *, void *);
++ } _u;
++ sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++#define sa_handler _u._sa_handler
++#define sa_sigaction _u._sa_sigaction
++
++#endif /* __KERNEL__ */
++
++typedef struct sigaltstack {
++ void *ss_sp;
++ int ss_flags;
++ size_t ss_size;
++} stack_t;
++
++#ifdef __KERNEL__
++
++#include <asm/sigcontext.h>
++#undef __HAVE_ARCH_SIG_BITOPS
++
++#define ptrace_signal_deliver(regs, cookie) do { } while (0)
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS2_SIGNAL_H */
+--- linux/include/asm-nios2nommu/smp.h
++++ linux/include/asm-nios2nommu/smp.h
+@@ -0,0 +1,34 @@
++#ifndef __ASM_SMP_H
++#define __ASM_SMP_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/smp.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++// #include <linux/config.h>
++
++#ifdef CONFIG_SMP
++#error SMP not supported
++#endif
++
++#endif
+--- linux/include/asm-nios2nommu/socket.h
++++ linux/include/asm-nios2nommu/socket.h
+@@ -0,0 +1,74 @@
++#ifndef _ASM_SOCKET_H
++#define _ASM_SOCKET_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/socket.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/sockios.h>
++
++/* For setsockopt(2) */
++#define SOL_SOCKET 1
++
++#define SO_DEBUG 1
++#define SO_REUSEADDR 2
++#define SO_TYPE 3
++#define SO_ERROR 4
++#define SO_DONTROUTE 5
++#define SO_BROADCAST 6
++#define SO_SNDBUF 7
++#define SO_RCVBUF 8
++#define SO_KEEPALIVE 9
++#define SO_OOBINLINE 10
++#define SO_NO_CHECK 11
++#define SO_PRIORITY 12
++#define SO_LINGER 13
++#define SO_BSDCOMPAT 14
++/* To add :#define SO_REUSEPORT 15 */
++#define SO_PASSCRED 16
++#define SO_PEERCRED 17
++#define SO_RCVLOWAT 18
++#define SO_SNDLOWAT 19
++#define SO_RCVTIMEO 20
++#define SO_SNDTIMEO 21
++
++/* Security levels - as per NRL IPv6 - don't actually do anything */
++#define SO_SECURITY_AUTHENTICATION 22
++#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
++#define SO_SECURITY_ENCRYPTION_NETWORK 24
++
++#define SO_BINDTODEVICE 25
++
++/* Socket filtering */
++#define SO_ATTACH_FILTER 26
++#define SO_DETACH_FILTER 27
++
++#define SO_PEERNAME 28
++#define SO_TIMESTAMP 29
++#define SCM_TIMESTAMP SO_TIMESTAMP
++
++#define SO_ACCEPTCONN 30
++
++#define SO_PEERSEC 31 /* ;dgt2;tmp; */
++
++#endif /* _ASM_SOCKET_H */
+--- linux/include/asm-nios2nommu/sockios.h
++++ linux/include/asm-nios2nommu/sockios.h
+@@ -0,0 +1,38 @@
++#ifndef _ASM_NIOS_SOCKIOS_H
++#define _ASM_NIOS_SOCKIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/sockios.h
++ *
++ * Socket-level I/O control calls.
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#define FIOSETOWN 0x8901
++#define SIOCSPGRP 0x8902
++#define FIOGETOWN 0x8903
++#define SIOCGPGRP 0x8904
++#define SIOCATMARK 0x8905
++#define SIOCGSTAMP 0x8906 /* Get stamp */
++
++#endif /* !(_ASM_NIOS_SOCKIOS_H) */
++
+--- linux/include/asm-nios2nommu/spi.h
++++ linux/include/asm-nios2nommu/spi.h
+@@ -0,0 +1,92 @@
++#ifndef _ASM_SPI_H_
++#define _ASM_SPI_H_ 1
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spi.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++int register_NIOS_SPI( void );
++void unregister_NIOS_SPI( void );
++
++#if defined(MODULE)
++void cleanup_module( void );
++int init_module( void );
++#endif
++
++#if defined(__KERNEL__)
++int spi_reset ( void );
++#endif
++
++
++#define clockCS 0x01
++#define temperatureCS 0x02
++
++#define clock_read_base 0x00
++#define clock_write_base 0x80
++#define clock_read_control 0x0F
++#define clock_read_trickle 0x11
++
++#define clock_read_sec 0x00
++#define clock_read_min 0x01
++#define clock_read_hour 0x02
++#define clock_read_day 0x03
++#define clock_read_date 0x04
++#define clock_read_month 0x05
++#define clock_read_year 0x06
++
++#define clock_write_control 0x8F
++#define clock_write_trickle 0x91
++#define clock_write_sec 0x80
++#define clock_write_min 0x81
++#define clock_write_hour 0x82
++#define clock_write_day 0x83
++#define clock_write_date 0x84
++#define clock_write_month 0x85
++#define clock_write_year 0x86
++
++#define clock_write_ram_start 0xA0
++#define clock_write_ram_end 0x100
++#define clock_read_ram_start 0x20
++#define clock_read_ram_end 0x80
++
++
++#define clock_sec_def 0x11
++#define clock_min_def 0x59
++#define clock_hour_def 0x71
++#define clock_day_def 0x00
++#define clock_date_def 0x20
++#define clock_month_def 0x12
++#define clock_year_def 0x34
++
++#define temp_read_base 0x00
++#define temp_write_base 0x80
++#define temp_read_control 0x00
++#define temp_write_control 0x80
++#define temp_read_msb 0x02
++#define temp_read_lsb 0x01
++
++#define MAX_TEMP_VAR 10
++
++#endif /*_ASM_SPI_H_*/
+--- linux/include/asm-nios2nommu/spinlock.h
++++ linux/include/asm-nios2nommu/spinlock.h
+@@ -0,0 +1,30 @@
++#ifndef __NIOS_SPINLOCK_H
++#define __NIOS_SPINLOCK_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/spinlock.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#error "Nios doesn't do SMP yet"
++
++#endif
+--- linux/include/asm-nios2nommu/stat.h
++++ linux/include/asm-nios2nommu/stat.h
+@@ -0,0 +1,102 @@
++#ifndef _ASMNIOS2NOMMU_STAT_H
++#define _ASMNIOS2NOMMU_STAT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/stat.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++struct __old_kernel_stat {
++ unsigned short st_dev;
++ unsigned short st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned long st_size;
++ unsigned long st_atime;
++ unsigned long st_mtime;
++ unsigned long st_ctime;
++};
++
++struct stat {
++ unsigned short st_dev;
++ unsigned short __pad1;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned short __pad2;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long __unused1;
++ unsigned long st_mtime;
++ unsigned long __unused2;
++ unsigned long st_ctime;
++ unsigned long __unused3;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++/* This matches struct stat64 in glibc2.1, hence the absolutely
++ * insane amounts of padding around dev_t's.
++ */
++struct stat64 {
++ unsigned long long st_dev;
++ unsigned char __pad1[4];
++
++#define STAT64_HAS_BROKEN_ST_INO 1
++ unsigned long __st_ino;
++
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++ unsigned char __pad3[4];
++
++ long long st_size;
++ unsigned long st_blksize;
++
++ unsigned long __pad4; /* future possible st_blocks high bits */
++ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long long st_ino;
++};
++
++#endif
+--- linux/include/asm-nios2nommu/statfs.h
++++ linux/include/asm-nios2nommu/statfs.h
+@@ -0,0 +1,30 @@
++#ifndef _NIOS2NOMMU_STATFS_H
++#define _NIOS2NOMMU_STATFS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/statfs.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/statfs.h>
++
++#endif /* _NIOS2NOMMU_STATFS_H */
+--- linux/include/asm-nios2nommu/string.h
++++ linux/include/asm-nios2nommu/string.h
+@@ -0,0 +1,45 @@
++#ifndef __NIOS_STRING_H__
++#define __NIOS_STRING_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/string.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#ifdef __KERNEL__ /* only set these up for kernel code */
++
++#define __HAVE_ARCH_MEMMOVE
++void * memmove(void * d, const void * s, size_t count);
++#define __HAVE_ARCH_MEMCPY
++extern void * memcpy(void *d, const void *s, size_t count);
++#define __HAVE_ARCH_MEMSET
++extern void * memset(void * s,int c,size_t count);
++
++#if 0
++#define __HAVE_ARCH_BCOPY
++#define __HAVE_ARCH_STRLEN
++#endif
++
++#endif /* KERNEL */
++
++#endif /* !(__NIOS_STRING_H__) */
+--- linux/include/asm-nios2nommu/system.h
++++ linux/include/asm-nios2nommu/system.h
+@@ -0,0 +1,172 @@
++/*
++ * Taken from the m68k.
++ *
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2NOMMU_SYSTEM_H
++#define _NIOS2NOMMU_SYSTEM_H
++
++// #include <linux/config.h> /* get configuration macros */
++#include <linux/linkage.h>
++#include <asm/segment.h>
++#include <asm/entry.h>
++#include <asm/nios.h>
++
++/*
++ * switch_to(n) should switch tasks to task ptr, first checking that
++ * ptr isn't the current task, in which case it does nothing. This
++ * also clears the TS-flag if the task we switched to has used the
++ * math co-processor latest.
++ */
++
++/*
++ */
++asmlinkage void resume(void);
++#define switch_to(prev,next,last) \
++{ \
++ void *_last; \
++ __asm__ __volatile__( \
++ "mov r4, %1\n" \
++ "mov r5, %2\n" \
++ "call resume\n" \
++ "mov %0,r4\n" \
++ : "=r" (_last) \
++ : "r" (prev), "r" (next) \
++ : "r4","r5","r7","r8","ra"); \
++ (last) = _last; \
++}
++
++#define local_irq_enable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "ori r8, r8, 1\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_irq_disable() __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "andi r8, r8, 0xfffe\n" \
++ "wrctl status, r8\n" \
++ : : : "r8")
++
++#define local_save_flags(x) __asm__ __volatile__ ( \
++ "rdctl r8, status\n" \
++ "mov %0, r8\n" \
++ :"=r" (x) : : "r8", "memory")
++
++#define local_irq_restore(x) __asm__ __volatile__ ( \
++ "mov r8, %0\n" \
++ "wrctl status, r8\n" \
++ : :"r" (x) : "memory")
++
++/* For spinlocks etc */
++#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
++
++#define irqs_disabled() \
++({ \
++ unsigned long flags; \
++ local_save_flags(flags); \
++ ((flags & NIOS2_STATUS_PIE_MSK) == 0x0); \
++})
++
++#define iret() __asm__ __volatile__ ("eret": : :"memory", "ea")
++
++/*
++ * Force strict CPU ordering.
++ * Not really required on m68k...
++ */
++#define nop() asm volatile ("nop"::)
++#define mb() asm volatile ("" : : :"memory")
++#define rmb() asm volatile ("" : : :"memory")
++#define wmb() asm volatile ("" : : :"memory")
++#define set_rmb(var, value) do { xchg(&var, value); } while (0)
++#define set_mb(var, value) set_rmb(var, value)
++#define set_wmb(var, value) do { var = value; wmb(); } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb() mb()
++#define smp_rmb() rmb()
++#define smp_wmb() wmb()
++#define smp_read_barrier_depends() read_barrier_depends()
++#else
++#define smp_mb() barrier()
++#define smp_rmb() barrier()
++#define smp_wmb() barrier()
++#define smp_read_barrier_depends() do { } while(0)
++#endif
++
++#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
++#define tas(ptr) (xchg((ptr),1))
++
++struct __xchg_dummy { unsigned long a[100]; };
++#define __xg(x) ((volatile struct __xchg_dummy *)(x))
++
++static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++{
++ unsigned long tmp, flags;
++
++ local_irq_save(flags);
++
++ switch (size) {
++ case 1:
++ __asm__ __volatile__( \
++ "ldb %0, %2\n" \
++ "stb %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 2:
++ __asm__ __volatile__( \
++ "ldh %0, %2\n" \
++ "sth %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ case 4:
++ __asm__ __volatile__( \
++ "ldw %0, %2\n" \
++ "stw %1, %2\n" \
++ : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
++ break;
++ }
++ local_irq_restore(flags);
++ return tmp;
++}
++
++/*
++ * Atomic compare and exchange. Compare OLD with MEM, if identical,
++ * store NEW in MEM. Return the initial value in MEM. Success is
++ * indicated by comparing RETURN with OLD.
++ */
++#define __HAVE_ARCH_CMPXCHG 1
++
++static __inline__ unsigned long
++cmpxchg(volatile int *p, int old, int new)
++{
++ unsigned long flags;
++ int prev;
++
++ local_irq_save(flags);
++ if ((prev = *p) == old)
++ *p = new;
++ local_irq_restore(flags);
++ return(prev);
++}
++
++#endif /* _NIOS2NOMMU_SYSTEM_H */
+--- linux/include/asm-nios2nommu/termbits.h
++++ linux/include/asm-nios2nommu/termbits.h
+@@ -0,0 +1,199 @@
++#ifndef __ARCH_NIOS_TERMBITS_H__
++#define __ARCH_NIOS_TERMBITS_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termbits.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/posix_types.h>
++
++typedef unsigned char cc_t;
++typedef unsigned int speed_t;
++typedef unsigned int tcflag_t;
++
++#define NCCS 19
++struct termios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++};
++
++/* c_cc characters */
++#define VINTR 0
++#define VQUIT 1
++#define VERASE 2
++#define VKILL 3
++#define VEOF 4
++#define VTIME 5
++#define VMIN 6
++#define VSWTC 7
++#define VSTART 8
++#define VSTOP 9
++#define VSUSP 10
++#define VEOL 11
++#define VREPRINT 12
++#define VDISCARD 13
++#define VWERASE 14
++#define VLNEXT 15
++#define VEOL2 16
++
++
++/* c_iflag bits */
++#define IGNBRK 0000001
++#define BRKINT 0000002
++#define IGNPAR 0000004
++#define PARMRK 0000010
++#define INPCK 0000020
++#define ISTRIP 0000040
++#define INLCR 0000100
++#define IGNCR 0000200
++#define ICRNL 0000400
++#define IUCLC 0001000
++#define IXON 0002000
++#define IXANY 0004000
++#define IXOFF 0010000
++#define IMAXBEL 0020000
++#define IUTF8 0040000
++
++/* c_oflag bits */
++#define OPOST 0000001
++#define OLCUC 0000002
++#define ONLCR 0000004
++#define OCRNL 0000010
++#define ONOCR 0000020
++#define ONLRET 0000040
++#define OFILL 0000100
++#define OFDEL 0000200
++#define NLDLY 0000400
++#define NL0 0000000
++#define NL1 0000400
++#define CRDLY 0003000
++#define CR0 0000000
++#define CR1 0001000
++#define CR2 0002000
++#define CR3 0003000
++#define TABDLY 0014000
++#define TAB0 0000000
++#define TAB1 0004000
++#define TAB2 0010000
++#define TAB3 0014000
++#define XTABS 0014000
++#define BSDLY 0020000
++#define BS0 0000000
++#define BS1 0020000
++#define VTDLY 0040000
++#define VT0 0000000
++#define VT1 0040000
++#define FFDLY 0100000
++#define FF0 0000000
++#define FF1 0100000
++
++/* c_cflag bit meaning */
++#define CBAUD 0010017
++#define B0 0000000 /* hang up */
++#define B50 0000001
++#define B75 0000002
++#define B110 0000003
++#define B134 0000004
++#define B150 0000005
++#define B200 0000006
++#define B300 0000007
++#define B600 0000010
++#define B1200 0000011
++#define B1800 0000012
++#define B2400 0000013
++#define B4800 0000014
++#define B9600 0000015
++#define B19200 0000016
++#define B38400 0000017
++#define EXTA B19200
++#define EXTB B38400
++#define CSIZE 0000060
++#define CS5 0000000
++#define CS6 0000020
++#define CS7 0000040
++#define CS8 0000060
++#define CSTOPB 0000100
++#define CREAD 0000200
++#define PARENB 0000400
++#define PARODD 0001000
++#define HUPCL 0002000
++#define CLOCAL 0004000
++#define CBAUDEX 0010000
++#define B57600 0010001
++#define B115200 0010002
++#define B230400 0010003
++#define B460800 0010004
++#define B500000 0010005
++#define B576000 0010006
++#define B921600 0010007
++#define B1000000 0010010
++#define B1152000 0010011
++#define B1500000 0010012
++#define B2000000 0010013
++#define B2500000 0010014
++#define B3000000 0010015
++#define B3500000 0010016
++#define B4000000 0010017
++#define CIBAUD 002003600000 /* input baud rate (not used) */
++#define CMSPAR 010000000000 /* mark or space (stick) parity */
++#define CRTSCTS 020000000000 /* flow control */
++
++/* c_lflag bits */
++#define ISIG 0000001
++#define ICANON 0000002
++#define XCASE 0000004
++#define ECHO 0000010
++#define ECHOE 0000020
++#define ECHOK 0000040
++#define ECHONL 0000100
++#define NOFLSH 0000200
++#define TOSTOP 0000400
++#define ECHOCTL 0001000
++#define ECHOPRT 0002000
++#define ECHOKE 0004000
++#define FLUSHO 0010000
++#define PENDIN 0040000
++#define IEXTEN 0100000
++
++
++/* tcflow() and TCXONC use these */
++#define TCOOFF 0
++#define TCOON 1
++#define TCIOFF 2
++#define TCION 3
++
++/* tcflush() and TCFLSH use these */
++#define TCIFLUSH 0
++#define TCOFLUSH 1
++#define TCIOFLUSH 2
++
++/* tcsetattr uses these */
++#define TCSANOW 0
++#define TCSADRAIN 1
++#define TCSAFLUSH 2
++
++#endif /* __ARCH_NIOS_TERMBITS_H__ */
+--- linux/include/asm-nios2nommu/termios.h
++++ linux/include/asm-nios2nommu/termios.h
+@@ -0,0 +1,132 @@
++#ifndef _NIOS_TERMIOS_H
++#define _NIOS_TERMIOS_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/termios.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/termbits.h>
++#include <asm/ioctls.h>
++
++struct winsize {
++ unsigned short ws_row;
++ unsigned short ws_col;
++ unsigned short ws_xpixel;
++ unsigned short ws_ypixel;
++};
++
++#define NCC 8
++struct termio {
++ unsigned short c_iflag; /* input mode flags */
++ unsigned short c_oflag; /* output mode flags */
++ unsigned short c_cflag; /* control mode flags */
++ unsigned short c_lflag; /* local mode flags */
++ unsigned char c_line; /* line discipline */
++ unsigned char c_cc[NCC]; /* control characters */
++};
++
++#ifdef __KERNEL__
++/* intr=^C quit=^| erase=del kill=^U
++ eof=^D vtime=\0 vmin=\1 sxtc=\0
++ start=^Q stop=^S susp=^Z eol=\0
++ reprint=^R discard=^U werase=^W lnext=^V
++ eol2=\0
++*/
++#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
++#endif
++
++/* modem lines */
++#define TIOCM_LE 0x001
++#define TIOCM_DTR 0x002
++#define TIOCM_RTS 0x004
++#define TIOCM_ST 0x008
++#define TIOCM_SR 0x010
++#define TIOCM_CTS 0x020
++#define TIOCM_CAR 0x040
++#define TIOCM_RNG 0x080
++#define TIOCM_DSR 0x100
++#define TIOCM_CD TIOCM_CAR
++#define TIOCM_RI TIOCM_RNG
++#define TIOCM_OUT1 0x2000
++#define TIOCM_OUT2 0x4000
++#define TIOCM_LOOP 0x8000
++
++/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
++
++/* line disciplines */
++#define N_TTY 0
++#define N_SLIP 1
++#define N_MOUSE 2
++#define N_PPP 3
++#define N_STRIP 4
++#define N_AX25 5
++#define N_X25 6 /* X.25 async */
++#define N_6PACK 7
++#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
++#define N_R3964 9 /* Reserved for Simatic R3964 module */
++#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
++#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
++#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
++#define N_HDLC 13 /* synchronous HDLC */
++#define N_SYNC_PPP 14
++#define N_HCI 15 /* Bluetooth HCI UART */
++
++#ifdef __KERNEL__
++
++/*
++ * Translate a "termio" structure into a "termios". Ugh.
++ */
++#define user_termio_to_kernel_termios(termios, termio) \
++({ \
++ unsigned short tmp; \
++ get_user(tmp, &(termio)->c_iflag); \
++ (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
++ get_user(tmp, &(termio)->c_oflag); \
++ (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
++ get_user(tmp, &(termio)->c_cflag); \
++ (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
++ get_user(tmp, &(termio)->c_lflag); \
++ (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
++ get_user((termios)->c_line, &(termio)->c_line); \
++ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
++})
++
++/*
++ * Translate a "termios" structure into a "termio". Ugh.
++ */
++#define kernel_termios_to_user_termio(termio, termios) \
++({ \
++ put_user((termios)->c_iflag, &(termio)->c_iflag); \
++ put_user((termios)->c_oflag, &(termio)->c_oflag); \
++ put_user((termios)->c_cflag, &(termio)->c_cflag); \
++ put_user((termios)->c_lflag, &(termio)->c_lflag); \
++ put_user((termios)->c_line, &(termio)->c_line); \
++ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
++})
++
++#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TERMIOS_H */
+--- linux/include/asm-nios2nommu/thread_info.h
++++ linux/include/asm-nios2nommu/thread_info.h
+@@ -0,0 +1,126 @@
++/* thread_info.h: niosnommu low-level thread information
++ * adapted from the m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd.
++ * Copyright (C) 2002 Microtronix Datacom
++ *
++ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _ASM_THREAD_INFO_H
++#define _ASM_THREAD_INFO_H
++
++#include <asm/page.h>
++
++#ifdef __KERNEL__
++
++#ifndef __ASSEMBLY__
++
++/*
++ * low level task data.
++ */
++struct thread_info {
++ struct task_struct *task; /* main task structure */
++ struct exec_domain *exec_domain; /* execution domain */
++ unsigned long flags; /* low level flags */
++ int cpu; /* cpu we're on */
++ int preempt_count; /* 0 => preemptable, <0 => BUG*/
++ struct restart_block restart_block;
++};
++
++/*
++ * macros/functions for gaining access to the thread information structure
++ */
++#define INIT_THREAD_INFO(tsk) \
++{ \
++ .task = &tsk, \
++ .exec_domain = &default_exec_domain, \
++ .flags = 0, \
++ .cpu = 0, \
++ .preempt_count = 1, \
++ .restart_block = { \
++ .fn = do_no_restart_syscall, \
++ }, \
++}
++
++#define init_thread_info (init_thread_union.thread_info)
++#define init_stack (init_thread_union.stack)
++
++
++/* how to get the thread information struct from C
++ usable only in supervisor mode */
++static inline struct thread_info *current_thread_info(void)
++{
++ struct thread_info *ti;
++ __asm__ __volatile__(
++ "mov %0, sp\n"
++ "and %0, %0, %1\n"
++ : "=&r"(ti)
++ : "r" (~(THREAD_SIZE-1))
++ );
++ return ti;
++}
++
++/* thread information allocation */
++#define alloc_thread_info(tsk) ((struct thread_info *) \
++ __get_free_pages(GFP_KERNEL, 1))
++#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
++#define put_thread_info(ti) put_task_struct((ti)->task)
++
++#define PREEMPT_ACTIVE 0x4000000
++
++/*
++ * thread information flag bit numbers
++ */
++#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
++#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
++#define TIF_SIGPENDING 2 /* signal pending */
++#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
++#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
++ TIF_NEED_RESCHED */
++
++/* as above, but as bit values */
++#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
++#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
++#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
++#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
++
++#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
++
++#else /* __ASSEMBLY__ */
++
++/* how to get the thread information struct from ASM
++ usable only in supervisor mode */
++.macro GET_THREAD_INFO reg
++.if THREAD_SIZE & 0xffff0000
++ andhi \reg, sp, %hi(~(THREAD_SIZE-1))
++.else
++ addi \reg, r0, %lo(~(THREAD_SIZE-1))
++ and \reg, \reg, sp
++.endif
++.endm
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_THREAD_INFO_H */
+--- linux/include/asm-nios2nommu/timer_struct.h
++++ linux/include/asm-nios2nommu/timer_struct.h
+@@ -0,0 +1,38 @@
++
++// ----------------------------------------------
++// Timer Peripheral
++
++// Timer Registers
++typedef volatile struct
++ {
++ int np_timerstatus; // read only, 2 bits (any write to clear TO)
++ int np_timercontrol; // write/readable, 4 bits
++ int np_timerperiodl; // write/readable, 16 bits
++ int np_timerperiodh; // write/readable, 16 bits
++ int np_timersnapl; // read only, 16 bits
++ int np_timersnaph; // read only, 16 bits
++ } np_timer;
++
++// Timer Register Bits
++enum
++ {
++ np_timerstatus_run_bit = 1, // timer is running
++ np_timerstatus_to_bit = 0, // timer has timed out
++
++ np_timercontrol_stop_bit = 3, // stop the timer
++ np_timercontrol_start_bit = 2, // start the timer
++ np_timercontrol_cont_bit = 1, // continous mode
++ np_timercontrol_ito_bit = 0, // enable time out interrupt
++
++ np_timerstatus_run_mask = (1<<1), // timer is running
++ np_timerstatus_to_mask = (1<<0), // timer has timed out
++
++ np_timercontrol_stop_mask = (1<<3), // stop the timer
++ np_timercontrol_start_mask = (1<<2), // start the timer
++ np_timercontrol_cont_mask = (1<<1), // continous mode
++ np_timercontrol_ito_mask = (1<<0) // enable time out interrupt
++ };
++
++// Timer Routines
++int nr_timer_milliseconds(void); // Starts on first call, hogs timer1.
++
+--- linux/include/asm-nios2nommu/timex.h
++++ linux/include/asm-nios2nommu/timex.h
+@@ -0,0 +1,48 @@
++#ifndef _ASMNIOS2NOMMU_TIMEX_H
++#define _ASMNIOS2NOMMU_TIMEX_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/timex.h
++ *
++ * timex specifications
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/nios.h>
++
++
++#define CLOCK_TICK_RATE nasys_clock_freq /* Underlying HZ */
++
++#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
++
++#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
++ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
++ << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
++
++typedef unsigned long cycles_t;
++
++static inline cycles_t get_cycles(void)
++{
++ return 0;
++}
++
++#endif
+--- linux/include/asm-nios2nommu/tlb.h
++++ linux/include/asm-nios2nommu/tlb.h
+@@ -0,0 +1,35 @@
++#ifndef __NIOS_TLB_H__
++#define __NIOS_TLB_H__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlb.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd
++ * Copyright (C) 2002 NEC Corporation
++ * Copyright (C) 2002 Miles Bader <miles@gnu.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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.
++ *
++ *
++ * Written by Miles Bader <miles@gnu.org>
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#define tlb_flush(tlb) ((void)0)
++
++#include <asm-generic/tlb.h>
++
++#endif /* __NIOS_TLB_H__ */
++
+--- linux/include/asm-nios2nommu/tlbflush.h
++++ linux/include/asm-nios2nommu/tlbflush.h
+@@ -0,0 +1,86 @@
++#ifndef _NIOS2NOMMU_TLBFLUSH_H
++#define _NIOS2NOMMU_TLBFLUSH_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/tlbflush.h
++ *
++ * Ported from m68knommu.
++ *
++ * Copyright (C) 2003 Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++#include <asm/setup.h>
++
++/*
++ * flush all user-space atc entries.
++ */
++static inline void __flush_tlb(void)
++{
++ BUG();
++}
++
++static inline void __flush_tlb_one(unsigned long addr)
++{
++ BUG();
++}
++
++#define flush_tlb() __flush_tlb()
++
++/*
++ * flush all atc entries (both kernel and user-space entries).
++ */
++static inline void flush_tlb_all(void)
++{
++ BUG();
++}
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++ BUG();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
++{
++ BUG();
++}
++
++static inline void flush_tlb_range(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_kernel_page(unsigned long addr)
++{
++ BUG();
++}
++
++extern inline void flush_tlb_pgtables(struct mm_struct *mm,
++ unsigned long start, unsigned long end)
++{
++ BUG();
++}
++
++#endif /* _NIOS2NOMMU_TLBFLUSH_H */
+--- linux/include/asm-nios2nommu/topology.h
++++ linux/include/asm-nios2nommu/topology.h
+@@ -0,0 +1,30 @@
++#ifndef _ASM_NIOS2NOMMU_TOPOLOGY_H
++#define _ASM_NIOS2NOMMU_TOPOLOGY_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/topology.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm-generic/topology.h>
++
++#endif /* _ASM_NIOS2NOMMU_TOPOLOGY_H */
+--- linux/include/asm-nios2nommu/traps.h
++++ linux/include/asm-nios2nommu/traps.h
+@@ -0,0 +1,27 @@
++/*
++ * Copyright (C) 2004, Microtronix Datacom Ltd.
++ *
++ * 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, GOOD TITLE or
++ * NON INFRINGEMENT. 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 _NIOS2_TRAPS_H
++#define _NIOS2_TRAPS_H
++
++#define TRAP_ID_SYSCALL 0
++#define TRAP_ID_APPDEBUG 1
++#endif /* !(_NIOS2_TRAPS_H) */
+--- linux/include/asm-nios2nommu/types.h
++++ linux/include/asm-nios2nommu/types.h
+@@ -0,0 +1,93 @@
++#ifndef _NIOS_TYPES_H
++#define _NIOS_TYPES_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/types.h
++ *
++ * Derived from m68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * This file is never included by application software unless
++ * explicitly requested (e.g., via linux/types.h) in which case the
++ * application is Linux specific so (user-) name space pollution is
++ * not a major issue. However, for interoperability, libraries still
++ * need to be careful to avoid a name clashes.
++ */
++
++#ifndef __ASSEMBLY__
++
++typedef unsigned short umode_t;
++
++/*
++ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
++ * header files exported to user space
++ */
++
++typedef __signed__ char __s8;
++typedef unsigned char __u8;
++
++typedef __signed__ short __s16;
++typedef unsigned short __u16;
++
++typedef __signed__ int __s32;
++typedef unsigned int __u32;
++
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++typedef __signed__ long long __s64;
++typedef unsigned long long __u64;
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * These aren't exported outside the kernel to avoid name space clashes
++ */
++#ifdef __KERNEL__
++
++#define BITS_PER_LONG 32
++
++#ifndef __ASSEMBLY__
++
++typedef signed char s8;
++typedef unsigned char u8;
++
++typedef signed short s16;
++typedef unsigned short u16;
++
++typedef signed int s32;
++typedef unsigned int u32;
++
++typedef signed long long s64;
++typedef unsigned long long u64;
++
++/* DMA addresses are always 32-bits wide */
++
++typedef u32 dma_addr_t;
++typedef u32 dma64_addr_t;
++
++typedef unsigned short kmem_bufctl_t;
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _NIOS_TYPES_H */
+--- linux/include/asm-nios2nommu/uaccess.h
++++ linux/include/asm-nios2nommu/uaccess.h
+@@ -0,0 +1,183 @@
++#ifndef __NIOS2NOMMU_UACCESS_H
++#define __NIOS2NOMMU_UACCESS_H
++
++/*--------------------------------------------------------------------
++ *
++ * asm-nios2nommu/uaccess.h
++ *
++ * User space memory access functions
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Ported from asm-m68knommu/uaccess.h --wentao
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <asm/segment.h>
++#include <asm/nios.h>
++
++#define VERIFY_READ 0
++#define VERIFY_WRITE 1
++
++#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
++
++static inline int _access_ok(unsigned long addr, unsigned long size)
++{
++ return (((unsigned long)addr < (unsigned long)nasys_program_mem_end) &&
++ (((unsigned long)addr >= (unsigned long)nasys_program_mem)));
++}
++
++extern inline int verify_area(int type, const void * addr, unsigned long size)
++{
++ return access_ok(type,addr,size)?0:-EFAULT;
++}
++
++/*
++ * The exception table consists of pairs of addresses: the first is the
++ * address of an instruction that is allowed to fault, and the second is
++ * the address at which the program should continue. No registers are
++ * modified, so it is entirely up to the continuation code to figure out
++ * what to do.
++ *
++ * All the routines below use bits of fixup code that are out of line
++ * with the main instruction path. This means when everything is well,
++ * we don't even have to jump over them. Further, they do not intrude
++ * on our cache or tlb entries.
++ */
++
++#define ARCH_HAS_SEARCH_EXTABLE
++//;dgt2;tmp;
++
++struct exception_table_entry
++{
++ unsigned long insn, fixup;
++};
++
++/* Returns 0 if exception not found and fixup otherwise. */
++extern unsigned long search_exception_table(unsigned long);
++
++
++/*
++ * These are the main single-value transfer routines. They automatically
++ * use the right size if we just have the right pointer type.
++ */
++
++#define put_user(x, ptr) \
++({ \
++ int __pu_err = 0; \
++ typeof(*(ptr)) __pu_val = (x); \
++ switch (sizeof (*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(ptr, &__pu_val, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __pu_err = __put_user_bad(); \
++ break; \
++ } \
++ __pu_err; \
++})
++#define __put_user(x, ptr) put_user(x, ptr)
++
++extern int __put_user_bad(void);
++
++/*
++ * Tell gcc we read from memory instead of writing: this is because
++ * we do not write to any memory gcc knows about, so there are no
++ * aliasing issues.
++ */
++
++#define __ptr(x) ((unsigned long *)(x))
++
++#define get_user(x, ptr) \
++({ \
++ int __gu_err = 0; \
++ typeof(*(ptr)) __gu_val = 0; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ case 2: \
++ case 4: \
++ case 8: \
++ memcpy(&__gu_val, ptr, sizeof (*(ptr))); \
++ break; \
++ default: \
++ __gu_val = 0; \
++ __gu_err = __get_user_bad(); \
++ break; \
++ } \
++ (x) = __gu_val; \
++ __gu_err; \
++})
++#define __get_user(x, ptr) get_user(x, ptr)
++
++extern int __get_user_bad(void);
++
++#define copy_from_user(to, from, n) (memcpy(to, from, n), 0)
++#define copy_to_user(to, from, n) (memcpy(to, from, n), 0)
++
++#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
++#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
++#define __copy_to_user_inatomic __copy_to_user
++#define __copy_from_user_inatomic __copy_from_user
++
++#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
++
++#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
++
++/*
++ * Copy a null terminated string from userspace.
++ */
++
++static inline long
++strncpy_from_user(char *dst, const char *src, long count)
++{
++ char *tmp;
++ strncpy(dst, src, count);
++ for (tmp = dst; *tmp && count > 0; tmp++, count--)
++ ;
++ return(tmp - dst); /* DAVIDM should we count a NUL ? check getname */
++}
++
++/*
++ * Return the size of a string (including the ending 0)
++ *
++ * Return 0 on exception, a value greater than N if too long
++ */
++static inline long strnlen_user(const char *src, long n)
++{
++ return(strlen(src) + 1); /* DAVIDM make safer */
++}
++
++#define strlen_user(str) strnlen_user(str, 32767)
++
++/*
++ * Zero Userspace
++ */
++
++static inline unsigned long
++clear_user(void *to, unsigned long n)
++{
++ memset(to, 0, n);
++ return(0);
++}
++
++#endif /* _NIOS2NOMMU_UACCESS_H */
+--- linux/include/asm-nios2nommu/uart_struct.h
++++ linux/include/asm-nios2nommu/uart_struct.h
+@@ -0,0 +1,83 @@
++
++// UART Registers
++typedef volatile struct
++ {
++ int np_uartrxdata; // Read-only, 8-bit
++ int np_uarttxdata; // Write-only, 8-bit
++ int np_uartstatus; // Read-only, 8-bit
++ int np_uartcontrol; // Read/Write, 9-bit
++ int np_uartdivisor; // Read/Write, 16-bit, optional
++ int np_uartendofpacket; // Read/Write, end-of-packet character
++ } np_uart;
++
++// UART Status Register Bits
++enum
++ {
++ np_uartstatus_eop_bit = 12,
++ np_uartstatus_cts_bit = 11,
++ np_uartstatus_dcts_bit = 10,
++ np_uartstatus_e_bit = 8,
++ np_uartstatus_rrdy_bit = 7,
++ np_uartstatus_trdy_bit = 6,
++ np_uartstatus_tmt_bit = 5,
++ np_uartstatus_toe_bit = 4,
++ np_uartstatus_roe_bit = 3,
++ np_uartstatus_brk_bit = 2,
++ np_uartstatus_fe_bit = 1,
++ np_uartstatus_pe_bit = 0,
++
++ np_uartstatus_eop_mask = (1<<12),
++ np_uartstatus_cts_mask = (1<<11),
++ np_uartstatus_dcts_mask = (1<<10),
++ np_uartstatus_e_mask = (1<<8),
++ np_uartstatus_rrdy_mask = (1<<7),
++ np_uartstatus_trdy_mask = (1<<6),
++ np_uartstatus_tmt_mask = (1<<5),
++ np_uartstatus_toe_mask = (1<<4),
++ np_uartstatus_roe_mask = (1<<3),
++ np_uartstatus_brk_mask = (1<<2),
++ np_uartstatus_fe_mask = (1<<1),
++ np_uartstatus_pe_mask = (1<<0)
++ };
++
++// UART Control Register Bits
++enum
++ {
++ np_uartcontrol_ieop_bit = 12,
++ np_uartcontrol_rts_bit = 11,
++ np_uartcontrol_idcts_bit = 10,
++ np_uartcontrol_tbrk_bit = 9,
++ np_uartcontrol_ie_bit = 8,
++ np_uartcontrol_irrdy_bit = 7,
++ np_uartcontrol_itrdy_bit = 6,
++ np_uartcontrol_itmt_bit = 5,
++ np_uartcontrol_itoe_bit = 4,
++ np_uartcontrol_iroe_bit = 3,
++ np_uartcontrol_ibrk_bit = 2,
++ np_uartcontrol_ife_bit = 1,
++ np_uartcontrol_ipe_bit = 0,
++
++ np_uartcontrol_ieop_mask = (1<<12),
++ np_uartcontrol_rts_mask = (1<<11),
++ np_uartcontrol_idcts_mask = (1<<10),
++ np_uartcontrol_tbrk_mask = (1<<9),
++ np_uartcontrol_ie_mask = (1<<8),
++ np_uartcontrol_irrdy_mask = (1<<7),
++ np_uartcontrol_itrdy_mask = (1<<6),
++ np_uartcontrol_itmt_mask = (1<<5),
++ np_uartcontrol_itoe_mask = (1<<4),
++ np_uartcontrol_iroe_mask = (1<<3),
++ np_uartcontrol_ibrk_mask = (1<<2),
++ np_uartcontrol_ife_mask = (1<<1),
++ np_uartcontrol_ipe_mask = (1<<0)
++ };
++
++// UART Routines
++int nr_uart_rxchar(np_uart *uartBase); // 0 for default UART
++void nr_uart_txcr(void);
++void nr_uart_txchar(int c,np_uart *uartBase); // 0 for default UART
++void nr_uart_txhex(int x); // 16 or 32 bits
++void nr_uart_txhex16(short x);
++void nr_uart_txhex32(long x);
++void nr_uart_txstring(char *s);
++
+--- linux/include/asm-nios2nommu/ucontext.h
++++ linux/include/asm-nios2nommu/ucontext.h
+@@ -0,0 +1,63 @@
++#ifndef _NIOSKNOMMU_UCONTEXT_H
++#define _NIOSKNOMMU_UCONTEXT_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/ucontext.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++typedef int greg_t;
++#define NGREG 32
++typedef greg_t gregset_t[NGREG];
++
++#ifdef CONFIG_FPU
++typedef struct fpregset {
++ int f_pcr;
++ int f_psr;
++ int f_fpiaddr;
++ int f_fpregs[8][3];
++} fpregset_t;
++#endif
++
++struct mcontext {
++ int version;
++ int status_extension;
++ gregset_t gregs;
++#ifdef CONFIG_FPU
++ fpregset_t fpregs;
++#endif
++};
++
++#define MCONTEXT_VERSION 2
++
++struct ucontext {
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct mcontext uc_mcontext;
++#ifdef CONFIG_FPU
++ unsigned long uc_filler[80];
++#endif
++ sigset_t uc_sigmask; /* mask last for extensibility */
++};
++
++#endif
+--- linux/include/asm-nios2nommu/unaligned.h
++++ linux/include/asm-nios2nommu/unaligned.h
+@@ -0,0 +1,43 @@
++#ifndef __NIOS_UNALIGNED_H
++#define __NIOS_UNALIGNED_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/unaligned.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * The nios cannot do unaligned accesses itself.
++ */
++
++#define get_unaligned(ptr) ({ \
++ typeof((*(ptr))) x; \
++ memcpy(&x, (void*)ptr, sizeof(*(ptr))); \
++ x; \
++})
++
++#define put_unaligned(val, ptr) ({ \
++ typeof((*(ptr))) x = val; \
++ memcpy((void*)ptr, &x, sizeof(*(ptr))); \
++})
++
++#endif /* __NIOS_UNALIGNED_H */
+--- linux/include/asm-nios2nommu/unistd.h
++++ linux/include/asm-nios2nommu/unistd.h
+@@ -0,0 +1,686 @@
++#ifndef _ASM_NIOS_UNISTD_H_
++#define _ASM_NIOS_UNISTD_H_
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/unistd.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * //vic - kernel_thread moved to process.c
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/traps.h>
++
++/* TRAP isr expects the trap# (syscall=#TRAP_ID_SYSCALL) in r2,
++ * the syscall # in r3, and arguments in r4, r5, ...
++ * Return argument expected in r2.
++ */
++
++#define __NR_restart_syscall 0
++#define __NR_exit 1
++#define __NR_fork 2
++#define __NR_read 3
++#define __NR_write 4
++#define __NR_open 5
++#define __NR_close 6
++#define __NR_waitpid 7
++#define __NR_creat 8
++#define __NR_link 9
++#define __NR_unlink 10
++#define __NR_execve 11
++#define __NR_chdir 12
++#define __NR_time 13
++#define __NR_mknod 14
++#define __NR_chmod 15
++#define __NR_chown 16
++#define __NR_break 17
++#define __NR_oldstat 18
++#define __NR_lseek 19
++#define __NR_getpid 20
++#define __NR_mount 21
++#define __NR_umount 22
++#define __NR_setuid 23
++#define __NR_getuid 24
++#define __NR_stime 25
++#define __NR_ptrace 26
++#define __NR_alarm 27
++#define __NR_oldfstat 28
++#define __NR_pause 29
++#define __NR_utime 30
++#define __NR_stty 31
++#define __NR_gtty 32
++#define __NR_access 33
++#define __NR_nice 34
++#define __NR_ftime 35
++#define __NR_sync 36
++#define __NR_kill 37
++#define __NR_rename 38
++#define __NR_mkdir 39
++#define __NR_rmdir 40
++#define __NR_dup 41
++#define __NR_pipe 42
++#define __NR_times 43
++#define __NR_prof 44
++#define __NR_brk 45
++#define __NR_setgid 46
++#define __NR_getgid 47
++#define __NR_signal 48
++#define __NR_geteuid 49
++#define __NR_getegid 50
++#define __NR_acct 51
++#define __NR_umount2 52 //vic #define __NR_phys 52
++#define __NR_lock 53
++#define __NR_ioctl 54
++#define __NR_fcntl 55
++#define __NR_mpx 56
++#define __NR_setpgid 57
++#define __NR_ulimit 58
++#define __NR_oldolduname 59
++#define __NR_umask 60
++#define __NR_chroot 61
++#define __NR_ustat 62
++#define __NR_dup2 63
++#define __NR_getppid 64
++#define __NR_getpgrp 65
++#define __NR_setsid 66
++#define __NR_sigaction 67
++#define __NR_sgetmask 68
++#define __NR_ssetmask 69
++#define __NR_setreuid 70
++#define __NR_setregid 71
++#define __NR_sigsuspend 72
++#define __NR_sigpending 73
++#define __NR_sethostname 74
++#define __NR_setrlimit 75
++#define __NR_getrlimit 76
++#define __NR_getrusage 77
++#define __NR_gettimeofday 78
++#define __NR_settimeofday 79
++#define __NR_getgroups 80
++#define __NR_setgroups 81
++#define __NR_select 82
++#define __NR_symlink 83
++#define __NR_oldlstat 84
++#define __NR_readlink 85
++#define __NR_uselib 86
++#define __NR_swapon 87
++#define __NR_reboot 88
++#define __NR_readdir 89
++#define __NR_mmap 90
++#define __NR_munmap 91
++#define __NR_truncate 92
++#define __NR_ftruncate 93
++#define __NR_fchmod 94
++#define __NR_fchown 95
++#define __NR_getpriority 96
++#define __NR_setpriority 97
++#define __NR_profil 98
++#define __NR_statfs 99
++#define __NR_fstatfs 100
++#define __NR_ioperm 101
++#define __NR_socketcall 102
++#define __NR_syslog 103
++#define __NR_setitimer 104
++#define __NR_getitimer 105
++#define __NR_stat 106
++#define __NR_lstat 107
++#define __NR_fstat 108
++#define __NR_olduname 109
++#define __NR_iopl /* 110 */ not supported
++#define __NR_vhangup 111
++#define __NR_idle /* 112 */ Obsolete
++#define __NR_vm86 /* 113 */ not supported
++#define __NR_wait4 114
++#define __NR_swapoff 115
++#define __NR_sysinfo 116
++#define __NR_ipc 117
++#define __NR_fsync 118
++#define __NR_sigreturn 119
++#define __NR_clone 120
++#define __NR_setdomainname 121
++#define __NR_uname 122
++#define __NR_cacheflush 123
++#define __NR_adjtimex 124
++#define __NR_mprotect 125
++#define __NR_sigprocmask 126
++#define __NR_create_module 127
++#define __NR_init_module 128
++#define __NR_delete_module 129
++#define __NR_get_kernel_syms 130
++#define __NR_quotactl 131
++#define __NR_getpgid 132
++#define __NR_fchdir 133
++#define __NR_bdflush 134
++#define __NR_sysfs 135
++#define __NR_personality 136
++#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
++#define __NR_setfsuid 138
++#define __NR_setfsgid 139
++#define __NR__llseek 140
++#define __NR_getdents 141
++#define __NR__newselect 142
++#define __NR_flock 143
++#define __NR_msync 144
++#define __NR_readv 145
++#define __NR_writev 146
++#define __NR_getsid 147
++#define __NR_fdatasync 148
++#define __NR__sysctl 149
++#define __NR_mlock 150
++#define __NR_munlock 151
++#define __NR_mlockall 152
++#define __NR_munlockall 153
++#define __NR_sched_setparam 154
++#define __NR_sched_getparam 155
++#define __NR_sched_setscheduler 156
++#define __NR_sched_getscheduler 157
++#define __NR_sched_yield 158
++#define __NR_sched_get_priority_max 159
++#define __NR_sched_get_priority_min 160
++#define __NR_sched_rr_get_interval 161
++#define __NR_nanosleep 162
++#define __NR_mremap 163
++#define __NR_setresuid 164
++#define __NR_getresuid 165
++#define __NR_getpagesize 166
++#define __NR_query_module 167
++#define __NR_poll 168
++#define __NR_nfsservctl 169
++#define __NR_setresgid 170
++#define __NR_getresgid 171
++#define __NR_prctl 172
++#define __NR_rt_sigreturn 173
++#define __NR_rt_sigaction 174
++#define __NR_rt_sigprocmask 175
++#define __NR_rt_sigpending 176
++#define __NR_rt_sigtimedwait 177
++#define __NR_rt_sigqueueinfo 178
++#define __NR_rt_sigsuspend 179
++#define __NR_pread 180
++#define __NR_pwrite 181
++#define __NR_lchown 182
++#define __NR_getcwd 183
++#define __NR_capget 184
++#define __NR_capset 185
++#define __NR_sigaltstack 186
++#define __NR_sendfile 187
++#define __NR_getpmsg 188 /* some people actually want streams */
++#define __NR_putpmsg 189 /* some people actually want streams */
++#define __NR_vfork 190
++#define __NR_ugetrlimit 191
++#define __NR_mmap2 192
++#define __NR_truncate64 193
++#define __NR_ftruncate64 194
++#define __NR_stat64 195
++#define __NR_lstat64 196
++#define __NR_fstat64 197
++#define __NR_chown32 198
++#define __NR_getuid32 199
++#define __NR_getgid32 200
++#define __NR_geteuid32 201
++#define __NR_getegid32 202
++#define __NR_setreuid32 203
++#define __NR_setregid32 204
++#define __NR_getgroups32 205
++#define __NR_setgroups32 206
++#define __NR_fchown32 207
++#define __NR_setresuid32 208
++#define __NR_getresuid32 209
++#define __NR_setresgid32 210
++#define __NR_getresgid32 211
++#define __NR_lchown32 212
++#define __NR_setuid32 213
++#define __NR_setgid32 214
++#define __NR_setfsuid32 215
++#define __NR_setfsgid32 216
++#define __NR_pivot_root 217
++/* 218 unused */
++/* 219 unused */
++#define __NR_getdents64 220
++#define __NR_gettid 221
++#define __NR_tkill 222
++#define __NR_setxattr 223
++#define __NR_lsetxattr 224
++#define __NR_fsetxattr 225
++#define __NR_getxattr 226
++#define __NR_lgetxattr 227
++#define __NR_fgetxattr 228
++#define __NR_listxattr 229
++#define __NR_llistxattr 230
++#define __NR_flistxattr 231
++#define __NR_removexattr 232
++#define __NR_lremovexattr 233
++#define __NR_fremovexattr 234
++#define __NR_futex 235
++#define __NR_sendfile64 236
++#define __NR_mincore 237
++#define __NR_madvise 238
++#define __NR_fcntl64 239
++#define __NR_readahead 240
++#define __NR_io_setup 241
++#define __NR_io_destroy 242
++#define __NR_io_getevents 243
++#define __NR_io_submit 244
++#define __NR_io_cancel 245
++#define __NR_fadvise64 246
++#define __NR_exit_group 247
++#define __NR_lookup_dcookie 248
++#define __NR_epoll_create 249
++#define __NR_epoll_ctl 250
++#define __NR_epoll_wait 251
++#define __NR_remap_file_pages 252
++#define __NR_set_tid_address 253
++#define __NR_timer_create 254
++#define __NR_timer_settime 255
++#define __NR_timer_gettime 256
++#define __NR_timer_getoverrun 257
++#define __NR_timer_delete 258
++#define __NR_clock_settime 259
++#define __NR_clock_gettime 260
++#define __NR_clock_getres 261
++#define __NR_clock_nanosleep 262
++#define __NR_statfs64 263
++#define __NR_fstatfs64 264
++#define __NR_tgkill 265
++#define __NR_utimes 266
++#define __NR_fadvise64_64 267
++#define __NR_mbind 268
++#define __NR_get_mempolicy 269
++#define __NR_set_mempolicy 270
++#define __NR_mq_open 271
++#define __NR_mq_unlink 272
++#define __NR_mq_timedsend 273
++#define __NR_mq_timedreceive 274
++#define __NR_mq_notify 275
++#define __NR_mq_getsetattr 276
++#define __NR_waitid 277
++#define __NR_sys_setaltroot 278
++#define __NR_add_key 279
++#define __NR_request_key 280
++#define __NR_keyctl 281
++
++#define NR_syscalls 282
++
++/* user-visible error numbers are in the range -1 - -122: see
++ <asm-nios2nommu/errno.h> */
++
++#define __syscall_return(type, res) \
++do { \
++ if ((unsigned long)(res) >= (unsigned long)(-125)) { \
++ \
++ /* avoid using res which is declared to be in \
++ register r2; errno might expand to a function \
++ call and clobber it. */ \
++ \
++ int __err = -(res); \
++ errno = __err; \
++ res = -1; \
++ } \
++ return (type) (res); \
++} while (0)
++
++#define _syscall0(type,name) \
++type name(void) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall1 arg a
++//;dgt2;tmp; already being in r4 ?
++#define _syscall1(type,name,atype,a) \
++type name(atype a) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall2 args a,b
++//;dgt2;tmp; already being in r4,r5 ?
++#define _syscall2(type,name,atype,a,btype,b) \
++type name(atype a,btype b) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall3 args a,b,c
++//;dgt2;tmp; already being in r4,r5,r6 ?
++#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
++type name(atype a,btype b,ctype c) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall4 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
++type name (atype a, btype b, ctype c, dtype d) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) d */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall5 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
++type name (atype a,btype b,ctype c,dtype d,etype e) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) c */ \
++ " mov r8, %7\n\t" /* (long) e */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ , "r" ((long) e) /* %7 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ , "r8" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++//;dgt2;tmp;can we RELY on syscall6 args a,b,c,d
++//;dgt2;tmp; already being in r4,r5,r6,r7 ?
++#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
++type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
++{ \
++ long __res; \
++ \
++ __asm__ __volatile__ ( \
++ \
++ " \n\t" \
++ \
++ " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \
++ " movi r3, %1\n\t" /* __NR_##name */ \
++ " mov r4, %3\n\t" /* (long) a */ \
++ " mov r5, %4\n\t" /* (long) b */ \
++ " mov r6, %5\n\t" /* (long) c */ \
++ " mov r7, %6\n\t" /* (long) c */ \
++ " mov r8, %7\n\t" /* (long) e */ \
++ " mov r9, %8\n\t" /* (long) f */ \
++ \
++ " trap\n\t" \
++ " mov %0, r2\n\t" /* syscall rtn */ \
++ \
++ " \n\t" \
++ \
++ : "=r" (__res) /* %0 */ \
++ \
++ : "i" (__NR_##name) /* %1 */ \
++ , "i" (TRAP_ID_SYSCALL) /* %2 */ \
++ , "r" ((long) a) /* %3 */ \
++ , "r" ((long) b) /* %4 */ \
++ , "r" ((long) c) /* %5 */ \
++ , "r" ((long) d) /* %6 */ \
++ , "r" ((long) e) /* %7 */ \
++ , "r" ((long) f) /* %8 */ \
++ \
++ : "r2" /* Clobbered */ \
++ , "r3" /* Clobbered */ \
++ , "r4" /* Clobbered */ \
++ , "r5" /* Clobbered */ \
++ , "r6" /* Clobbered */ \
++ , "r7" /* Clobbered */ \
++ , "r8" /* Clobbered */ \
++ , "r9" /* Clobbered */ \
++ ); \
++ \
++__syscall_return(type,__res); \
++}
++
++#ifdef __KERNEL__
++#define __ARCH_WANT_IPC_PARSE_VERSION
++#define __ARCH_WANT_OLD_READDIR
++#define __ARCH_WANT_OLD_STAT
++#define __ARCH_WANT_STAT64
++#define __ARCH_WANT_SYS_ALARM
++#define __ARCH_WANT_SYS_GETHOSTNAME
++#define __ARCH_WANT_SYS_PAUSE
++#define __ARCH_WANT_SYS_SGETMASK
++#define __ARCH_WANT_SYS_SIGNAL
++#define __ARCH_WANT_SYS_TIME
++#define __ARCH_WANT_SYS_UTIME
++#define __ARCH_WANT_SYS_WAITPID
++#define __ARCH_WANT_SYS_SOCKETCALL
++#define __ARCH_WANT_SYS_FADVISE64
++#define __ARCH_WANT_SYS_GETPGRP
++#define __ARCH_WANT_SYS_LLSEEK
++#define __ARCH_WANT_SYS_NICE
++#define __ARCH_WANT_SYS_OLD_GETRLIMIT
++#define __ARCH_WANT_SYS_OLDUMOUNT
++#define __ARCH_WANT_SYS_SIGPENDING
++#define __ARCH_WANT_SYS_SIGPROCMASK
++#define __ARCH_WANT_SYS_RT_SIGACTION
++#endif
++
++#ifdef __KERNEL_SYSCALLS__
++
++/*
++ * we need this inline - forking from kernel space will result
++ * in NO COPY ON WRITE (!!!), until an execve is executed. This
++ * is no problem, but for the stack. This is handled by not letting
++ * main() use the stack at all after fork(). Thus, no function
++ * calls - which means inline code for fork too, as otherwise we
++ * would use the stack upon exit from 'fork()'.
++ *
++ * Actually only pause and fork are needed inline, so that there
++ * won't be any messing with the stack from main(), but we define
++ * some others too.
++ */
++#define __NR__exit __NR_exit
++static inline _syscall0(int,pause)
++static inline _syscall0(int,sync)
++static inline _syscall0(pid_t,setsid)
++static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
++static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
++static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
++static inline _syscall1(int,dup,int,fd)
++static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
++static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
++static inline _syscall1(int,close,int,fd)
++static inline _syscall1(int,_exit,int,exitcode)
++static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
++static inline _syscall1(int,delete_module,const char *,name)
++
++static inline pid_t wait(int * wait_stat)
++{
++ return waitpid(-1,wait_stat,0);
++}
++
++#endif
++
++/*
++ * "Conditional" syscalls
++ *
++ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
++ * but it doesn't work on all toolchains, so we just do it by hand
++ */
++#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
++
++#endif /* _ASM_NIOS_UNISTD_H_ */
+--- linux/include/asm-nios2nommu/user.h
++++ linux/include/asm-nios2nommu/user.h
+@@ -0,0 +1,112 @@
++#ifndef _NIOS2NOMMU_USER_H
++#define _NIOS2NOMMU_USER_H
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/user.h
++ *
++ * Derived from M68knommu
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++#include <asm/page.h>
++
++/* Core file format: The core file is written in such a way that gdb
++ can understand it and provide useful information to the user (under
++ linux we use the 'trad-core' bfd). There are quite a number of
++ obstacles to being able to view the contents of the floating point
++ registers, and until these are solved you will not be able to view the
++ contents of them. Actually, you can read in the core file and look at
++ the contents of the user struct to find out what the floating point
++ registers contain.
++ The actual file contents are as follows:
++ UPAGE: 1 page consisting of a user struct that tells gdb what is present
++ in the file. Directly after this is a copy of the task_struct, which
++ is currently not used by gdb, but it may come in useful at some point.
++ All of the registers are stored as part of the upage. The upage should
++ always be only one page.
++ DATA: The data area is stored. We use current->end_text to
++ current->brk to pick up all of the user variables, plus any memory
++ that may have been malloced. No attempt is made to determine if a page
++ is demand-zero or if a page is totally unused, we just cover the entire
++ range. All of the addresses are rounded in such a way that an integral
++ number of pages is written.
++ STACK: We need the stack information in order to get a meaningful
++ backtrace. We need to write the data from (esp) to
++ current->start_stack, so we round each of these off in order to be able
++ to write an integer number of pages.
++ The minimum core file size is 3 pages, or 12288 bytes.
++*/
++
++struct user_m68kfp_struct {
++ unsigned long fpregs[8*3]; /* fp0-fp7 registers */
++ unsigned long fpcntl[3]; /* fp control regs */
++};
++
++/* This is needs more work, probably should look like gdb useage */
++struct user_regs_struct {
++ long r1,r2,r3,r4,r5,r6,r7,r8;
++ long r9,r10,r11,r12,r13,r14,r15;
++ long r16,r17,r18,r19,r20,r21,r22,r23;
++ long gp;
++ long sp;
++ long ra;
++ long fp;
++ long orig_r2;
++ long estatus;
++ long status_extension;
++ long ea;
++};
++
++
++/* When the kernel dumps core, it starts by dumping the user struct -
++ this will be used by gdb to figure out where the data and stack segments
++ are within the file, and what virtual addresses to use. */
++struct user{
++/* We start with the registers, to mimic the way that "memory" is returned
++ from the ptrace(3,...) function. */
++ struct user_regs_struct regs; /* Where the registers are actually stored */
++/* ptrace does not yet supply these. Someday.... */
++ int u_fpvalid; /* True if math co-processor being used. */
++ /* for this mess. Not yet used. */
++ struct user_m68kfp_struct m68kfp; /* Math Co-processor registers. */
++/* The rest of this junk is to help gdb figure out what goes where */
++ unsigned long int u_tsize; /* Text segment size (pages). */
++ unsigned long int u_dsize; /* Data segment size (pages). */
++ unsigned long int u_ssize; /* Stack segment size (pages). */
++ unsigned long start_code; /* Starting virtual address of text. */
++ unsigned long start_stack; /* Starting virtual address of stack area.
++ This is actually the bottom of the stack,
++ the top of the stack is always found in the
++ esp register. */
++ long int signal; /* Signal that caused the core dump. */
++ int reserved; /* No longer used */
++ struct user_regs_struct *u_ar0;
++ /* Used by gdb to help find the values for */
++ /* the registers. */
++ struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */
++ unsigned long magic; /* To uniquely identify a core file */
++ char u_comm[32]; /* User command that was responsible */
++};
++#define NBPG PAGE_SIZE
++#define UPAGES 1
++#define HOST_TEXT_START_ADDR (u.start_code)
++#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
++
++#endif
+--- linux/include/asm-nios2nommu/virtconvert.h
++++ linux/include/asm-nios2nommu/virtconvert.h
+@@ -0,0 +1,47 @@
++#ifndef __NIOS_VIRT_CONVERT__
++#define __NIOS_VIRT_CONVERT__
++
++/*--------------------------------------------------------------------
++ *
++ * include/asm-nios2nommu/virtconvert.h
++ *
++ * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
++ *
++ * Copyright (C) 2004 Microtronix Datacom Ltd
++ *
++ * 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.
++ *
++ *
++ * Jan/20/2004 dgt NiosII
++ *
++ ---------------------------------------------------------------------*/
++
++
++/*
++ * Macros used for converting between virtual and physical mappings.
++ */
++
++#ifdef __KERNEL__
++
++// #include <linux/config.h>
++#include <asm/setup.h>
++#include <asm/page.h>
++
++#define mm_ptov(vaddr) ((void *) (vaddr))
++#define mm_vtop(vaddr) ((unsigned long) (vaddr))
++#define phys_to_virt(vaddr) ((void *) (vaddr))
++#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
++
++#define virt_to_bus virt_to_phys
++#define bus_to_virt phys_to_virt
++
++#endif /*__KERNEL__ */
++#endif /*__NIOS_VIRT_CONVERT__*/
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-001-lzma-vmlinuz.00.patch b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-001-lzma-vmlinuz.00.patch
new file mode 100644
index 0000000000..87e50f8be7
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-001-lzma-vmlinuz.00.patch
@@ -0,0 +1,27017 @@
+diff --git a/.miniconfig b/.miniconfig
+new file mode 100644
+index 0000000..5686e53
+--- /dev/null
++++ b/.miniconfig
+@@ -0,0 +1,89 @@
++#make allnoconfig KCONFIG_ALLCONFIG=miniconfig
++CONFIG_X86_32=y
++CONFIG_CLOCKSOURCE_WATCHDOG=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_MMU=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_DMI=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_PRINTK=y
++CONFIG_BASE_SMALL=1
++CONFIG_BLOCK=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_X86_GENERIC=y
++CONFIG_X86_L1_CACHE_SHIFT=7
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_X86_WP_WORKS_OK=y
++CONFIG_X86_BSWAP=y
++CONFIG_X86_CMPXCHG64=y
++CONFIG_X86_INTEL_USERCOPY=y
++CONFIG_X86_TSC=y
++CONFIG_PREEMPT_NONE=y
++CONFIG_VM86=y
++CONFIG_HIGHMEM=y
++CONFIG_FLATMEM=y
++CONFIG_MTRR=y
++CONFIG_HZ_250=y
++CONFIG_PHYSICAL_ALIGN=0x100000
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_PM=y
++CONFIG_ACPI=y
++CONFIG_ACPI_SLEEP=y
++CONFIG_ACPI_BLACKLIST_YEAR=0
++CONFIG_ACPI_EC=y
++CONFIG_ACPI_SYSTEM=y
++CONFIG_PCI=y
++CONFIG_PCI_GOANY=y
++CONFIG_PCI_DIRECT=y
++CONFIG_BINFMT_ELF=y
++CONFIG_STANDALONE=y
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=2
++CONFIG_BLK_DEV_IDE=y
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_BLK_DEV_IDECD=y
++CONFIG_IDE_GENERIC=y
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++CONFIG_SERIO=y
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_VGA_CONSOLE=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_EXT2_FS=y
++CONFIG_DNOTIFY=y
++CONFIG_ISO9660_FS=y
++CONFIG_FAT_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_RAMFS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_AUFS=y
++CONFIG_AUFS_FAKE_DM=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_DOUBLEFAULT=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_HAS_IOPORT=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_KTIME_SCALAR=y
+diff --git a/Makefile b/Makefile
+index d970cb1..a369204 100644
+--- a/Makefile
++++ b/Makefile
+@@ -188,7 +188,7 @@ CROSS_COMPILE ?=
+ # Architecture as present in compile.h
+ UTS_MACHINE := $(ARCH)
+
+-KCONFIG_CONFIG ?= .config
++KCONFIG_CONFIG ?= .miniconfig
+
+ # SHELL used by kbuild
+ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
+diff --git a/arch/i386/boot/compressed/LzmaDecode.c b/arch/i386/boot/compressed/LzmaDecode.c
+new file mode 100644
+index 0000000..21bf40b
+--- /dev/null
++++ b/arch/i386/boot/compressed/LzmaDecode.c
+@@ -0,0 +1,588 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder (optimized for Speed version)
++
++ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this Code, expressly permits you to
++ statically or dynamically link your Code (or bind by name) to the
++ interfaces of this file without subjecting your linked Code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_READ_BYTE (*Buffer++)
++
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
++
++#ifdef _LZMA_IN_CB
++
++#define RC_TEST { if (Buffer == BufferLim) \
++ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
++
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
++
++#else
++
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
++
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
++
++#endif
++
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
++
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
++
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
++ { UpdateBit0(p); mi <<= 1; A0; } else \
++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
++
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
++
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
++ { int i = numLevels; res = 1; \
++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
++ res -= (1 << numLevels); }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
++{
++ unsigned char prop0;
++ if (size < LZMA_PROPERTIES_SIZE)
++ return LZMA_RESULT_DATA_ERROR;
++ prop0 = propsData[0];
++ if (prop0 >= (9 * 5 * 5))
++ return LZMA_RESULT_DATA_ERROR;
++ {
++ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
++ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
++ propsRes->lc = prop0;
++ /*
++ unsigned char remainder = (unsigned char)(prop0 / 9);
++ propsRes->lc = prop0 % 9;
++ propsRes->pb = remainder / 5;
++ propsRes->lp = remainder % 5;
++ */
++ }
++
++ #ifdef _LZMA_OUT_READ
++ {
++ int i;
++ propsRes->DictionarySize = 0;
++ for (i = 0; i < 4; i++)
++ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
++ if (propsRes->DictionarySize == 0)
++ propsRes->DictionarySize = 1;
++ }
++ #endif
++ return LZMA_RESULT_OK;
++}
++
++#define kLzmaStreamWasFinishedId (-1)
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
++{
++ CProb *p = vs->Probs;
++ SizeT nowPos = 0;
++ Byte previousByte = 0;
++ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
++ int lc = vs->Properties.lc;
++
++ #ifdef _LZMA_OUT_READ
++
++ UInt32 Range = vs->Range;
++ UInt32 Code = vs->Code;
++ #ifdef _LZMA_IN_CB
++ const Byte *Buffer = vs->Buffer;
++ const Byte *BufferLim = vs->BufferLim;
++ #else
++ const Byte *Buffer = inStream;
++ const Byte *BufferLim = inStream + inSize;
++ #endif
++ int state = vs->State;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++ UInt32 distanceLimit = vs->DistanceLimit;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->Properties.DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ Byte tempDictionary[4];
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++ if (len == kLzmaStreamWasFinishedId)
++ return LZMA_RESULT_OK;
++
++ if (dictionarySize == 0)
++ {
++ dictionary = tempDictionary;
++ dictionarySize = 1;
++ tempDictionary[0] = vs->TempDictionary[0];
++ }
++
++ if (len == kLzmaNeedInitId)
++ {
++ {
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ UInt32 i;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ rep0 = rep1 = rep2 = rep3 = 1;
++ state = 0;
++ globalPos = 0;
++ distanceLimit = 0;
++ dictionaryPos = 0;
++ dictionary[dictionarySize - 1] = 0;
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++ }
++ len = 0;
++ }
++ while(len != 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++
++ #else /* if !_LZMA_OUT_READ */
++
++ int state = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ int len = 0;
++ const Byte *Buffer;
++ const Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++
++ {
++ UInt32 i;
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ }
++
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++
++ #endif /* _LZMA_OUT_READ */
++
++ while(nowPos < outSize)
++ {
++ CProb *prob;
++ UInt32 bound;
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++
++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ int symbol = 1;
++ UpdateBit0(prob)
++ prob = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state >= kNumLitStates)
++ {
++ int matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ do
++ {
++ int bit;
++ CProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & 0x100);
++ probLit = prob + 0x100 + bit + symbol;
++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
++ }
++ while (symbol < 0x100);
++ }
++ while (symbol < 0x100)
++ {
++ CProb *probLit = prob + symbol;
++ RC_GET_BIT(probLit, symbol)
++ }
++ previousByte = (Byte)symbol;
++
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRep + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < kNumLitStates ? 0 : 3;
++ prob = p + LenCoder;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG0 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ UpdateBit0(prob);
++
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit == 0)
++ #else
++ if (nowPos == 0)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ state = state < kNumLitStates ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++ #endif
++
++ continue;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ UpdateBit1(prob);
++ prob = p + IsRepG1 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep1;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG2 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep2;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ state = state < kNumLitStates ? 8 : 11;
++ prob = p + RepLenCoder;
++ }
++ {
++ int numBits, offset;
++ CProb *probLen = prob + LenChoice;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ numBits = kLenNumLowBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenChoice2;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ numBits = kLenNumMidBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ numBits = kLenNumHighBits;
++ }
++ }
++ RangeDecoderBitTreeDecode(probLen, numBits, len);
++ len += offset;
++ }
++
++ if (state < 4)
++ {
++ int posSlot;
++ state += kNumLitStates;
++ prob = p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits);
++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = (2 | ((UInt32)posSlot & 1));
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 <<= numDirectBits;
++ prob = p + SpecPos + rep0 - posSlot - 1;
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ RC_NORMALIZE
++ Range >>= 1;
++ rep0 <<= 1;
++ if (Code >= Range)
++ {
++ Code -= Range;
++ rep0 |= 1;
++ }
++ }
++ while (--numDirectBits != 0);
++ prob = p + Align;
++ rep0 <<= kNumAlignBits;
++ numDirectBits = kNumAlignBits;
++ }
++ {
++ int i = 1;
++ int mi = 1;
++ do
++ {
++ CProb *prob3 = prob + mi;
++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
++ i <<= 1;
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ else
++ rep0 = posSlot;
++ if (++rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = kLzmaStreamWasFinishedId;
++ break;
++ }
++ }
++
++ len += kMatchMinLen;
++ #ifdef _LZMA_OUT_READ
++ if (rep0 > distanceLimit)
++ #else
++ if (rep0 > nowPos)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ #ifdef _LZMA_OUT_READ
++ if (dictionarySize - distanceLimit > (UInt32)len)
++ distanceLimit += len;
++ else
++ distanceLimit = dictionarySize;
++ #endif
++
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ len--;
++ outStream[nowPos++] = previousByte;
++ }
++ while(len != 0 && nowPos < outSize);
++ }
++ }
++ RC_NORMALIZE;
++
++ #ifdef _LZMA_OUT_READ
++ vs->Range = Range;
++ vs->Code = Code;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + (UInt32)nowPos;
++ vs->DistanceLimit = distanceLimit;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->RemainLen = len;
++ vs->TempDictionary[0] = tempDictionary[0];
++ #endif
++
++ #ifdef _LZMA_IN_CB
++ vs->Buffer = Buffer;
++ vs->BufferLim = BufferLim;
++ #else
++ *inSizeProcessed = (SizeT)(Buffer - inStream);
++ #endif
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff --git a/arch/i386/boot/compressed/LzmaDecode.h b/arch/i386/boot/compressed/LzmaDecode.h
+new file mode 100644
+index 0000000..213062a
+--- /dev/null
++++ b/arch/i386/boot/compressed/LzmaDecode.h
+@@ -0,0 +1,131 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++/* #define _LZMA_SYSTEM_SIZE_T */
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifndef SizeT
++#ifdef _LZMA_SYSTEM_SIZE_T
++#include <stddef.h>
++#define SizeT size_t
++#else
++#define SizeT UInt32
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_PROPERTIES_SIZE 5
++
++typedef struct _CLzmaProperties
++{
++ int lc;
++ int lp;
++ int pb;
++ #ifdef _LZMA_OUT_READ
++ UInt32 DictionarySize;
++ #endif
++}CLzmaProperties;
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
++
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
++
++#define kLzmaNeedInitId (-2)
++
++typedef struct _CLzmaDecoderState
++{
++ CLzmaProperties Properties;
++ CProb *Probs;
++
++ #ifdef _LZMA_IN_CB
++ const unsigned char *Buffer;
++ const unsigned char *BufferLim;
++ #endif
++
++ #ifdef _LZMA_OUT_READ
++ unsigned char *Dictionary;
++ UInt32 Range;
++ UInt32 Code;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 DistanceLimit;
++ UInt32 Reps[4];
++ int State;
++ int RemainLen;
++ unsigned char TempDictionary[4];
++ #endif
++} CLzmaDecoderState;
++
++#ifdef _LZMA_OUT_READ
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
++#endif
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
++
++#endif
+diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
+index a661217..fb40869 100644
+--- a/arch/i386/boot/compressed/Makefile
++++ b/arch/i386/boot/compressed/Makefile
+@@ -4,15 +4,16 @@
+ # create a compressed vmlinux image from the original vmlinux
+ #
+
+-targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
+- vmlinux.bin.all vmlinux.relocs
++tragets := head.o lzma_misc.o piggy.o \
++ vmlinux.bin.all vmlinux.relocs \
++ vmlinux vmlinux.bin vmlinux.bin.gz
+ EXTRA_AFLAGS := -traditional
+
+ LDFLAGS_vmlinux := -T
+-CFLAGS_misc.o += -fPIC
++CFLAGS_lzma_misc.o += -fPIC
+ hostprogs-y := relocs
+
+-$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
++$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/lzma_misc.o $(obj)/piggy.o FORCE
+ $(call if_changed,ld)
+ @:
+
+@@ -33,10 +34,10 @@ $(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
+
+ ifdef CONFIG_RELOCATABLE
+ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
+- $(call if_changed,gzip)
++ $(call if_changed,lzma)
+ else
+ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+- $(call if_changed,gzip)
++ $(call if_changed,lzma)
+ endif
+
+ LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+diff --git a/arch/i386/boot/compressed/lzma_misc.c b/arch/i386/boot/compressed/lzma_misc.c
+new file mode 100644
+index 0000000..4f5f7f9
+--- /dev/null
++++ b/arch/i386/boot/compressed/lzma_misc.c
+@@ -0,0 +1,290 @@
++/*
++ * lzma_misc.c
++ *
++ * Decompress LZMA compressed vmlinuz
++ * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com
++ * Program adapted from misc.c for 2.6.20.1 kernel
++ * Please refer to misc.c for authorship and copyright.
++ * Date: 25 March 2007
++ * Source released under GPL
++ */
++
++#undef CONFIG_PARAVIRT
++#include <linux/linkage.h>
++#include <linux/vmalloc.h>
++#include <linux/screen_info.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/boot.h>
++
++/* WARNING!!
++ * This code is compiled with -fPIC and it is relocated dynamically
++ * at run time, but no relocation processing is performed.
++ * This means that it is not safe to place pointers in static structures.
++ */
++
++#define OF(args) args
++#define STATIC static
++
++#undef memset
++#undef memcpy
++
++typedef unsigned char uch;
++typedef unsigned short ush;
++typedef unsigned long ulg;
++
++#define WSIZE 0x80000000 /* Window size must be at least 32k,
++ * and a power of two
++ * We don't actually have a window just
++ * a huge output buffer so I report
++ * a 2G windows size, as that should
++ * always be larger than our output buffer.
++ */
++
++static uch *inbuf; /* input buffer */
++static uch *window; /* Sliding window buffer, (and final output buffer) */
++
++static unsigned insize; /* valid bytes in inbuf */
++static unsigned inptr; /* index of next byte to be processed in inbuf */
++
++/* 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 */
++
++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
++
++/* Diagnostic functions */
++#ifdef DEBUG
++# define Assert(cond,msg) {if(!(cond)) error(msg);}
++# define Trace(x) fprintf x
++# define Tracev(x) {if (verbose) fprintf x ;}
++# define Tracevv(x) {if (verbose>1) fprintf x ;}
++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#else
++# define Assert(cond,msg)
++# define Trace(x)
++# define Tracev(x)
++# define Tracevv(x)
++# define Tracec(c,x)
++# define Tracecv(c,x)
++#endif
++
++static int fill_inbuf(void);
++static void error(char *m);
++
++/*
++ * This is set up by the setup-routine at boot-time
++ */
++static unsigned char *real_mode; /* Pointer to real-mode data */
++
++#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
++#ifndef STANDARD_MEMORY_BIOS_CALL
++#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
++#endif
++#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
++
++extern unsigned char input_data[];
++extern int input_len;
++
++static long bytes_out = 0;
++
++static void *memcpy(void *dest, const void *src, unsigned n);
++
++static void putstr(const char *);
++
++static unsigned long free_mem_ptr;
++static unsigned long free_mem_end_ptr;
++
++#define HEAP_SIZE 0x3000
++
++static char *vidmem = (char *)0xb8000;
++static int vidport;
++static int lines, cols;
++
++#ifdef CONFIG_X86_NUMAQ
++void *xquad_portio;
++#endif
++
++static void scroll(void)
++{
++ int i;
++
++ memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
++ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
++ vidmem[i] = ' ';
++}
++
++static void putstr(const char *s)
++{
++ int x,y,pos;
++ char c;
++
++ x = RM_SCREEN_INFO.orig_x;
++ y = RM_SCREEN_INFO.orig_y;
++
++ while ( ( c = *s++ ) != '\0' ) {
++ if ( c == '\n' ) {
++ x = 0;
++ if ( ++y >= lines ) {
++ scroll();
++ y--;
++ }
++ } else {
++ vidmem [ ( x + cols * y ) * 2 ] = c;
++ if ( ++x >= cols ) {
++ x = 0;
++ if ( ++y >= lines ) {
++ scroll();
++ y--;
++ }
++ }
++ }
++ }
++
++ RM_SCREEN_INFO.orig_x = x;
++ RM_SCREEN_INFO.orig_y = y;
++
++ pos = (x + cols * y) * 2; /* Update cursor position */
++ outb_p(14, vidport);
++ outb_p(0xff & (pos >> 9), vidport+1);
++ outb_p(15, vidport);
++ outb_p(0xff & (pos >> 1), vidport+1);
++}
++
++static void* memcpy(void* dest, const void* src, unsigned n)
++{
++ int i;
++ char *d = (char *)dest, *s = (char *)src;
++
++ for (i=0;i<n;i++) d[i] = s[i];
++ return dest;
++}
++
++/* ===========================================================================
++ * Fill the input buffer. This is called only when the buffer is empty
++ * and at least one byte is really needed.
++ */
++static int fill_inbuf(void)
++{
++ error("ran out of input data");
++ return 0;
++}
++
++/* ===========================================================================
++ */
++static void error(char *x)
++{
++ putstr("\n\n");
++ putstr(x);
++ putstr("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++#define _LZMA_IN_CB
++#include "LzmaDecode.h"
++#include "LzmaDecode.c"
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
++
++/*
++ * Do the lzma decompression
++ */
++static int lzma_unzip(uch* output)
++{
++
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++
++ ILzmaInCallback callback;
++ callback.Read = read_byte;
++
++ // lzma args
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ // skip dictionary size
++ for (i = 0; i < 4; i++)
++ get_byte();
++ // get uncompressed size
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // skip high order bytes
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ // Just point it beyond
++ state.Probs = (CProb*) ( free_mem_ptr );
++ // decompress kernel
++ if (LzmaDecode( &state, &callback,
++ (unsigned char*)output, uncompressedSize, &i) == LZMA_RESULT_OK)
++ {
++ if ( i != uncompressedSize )
++ error( "kernel corrupted!\n");
++ bytes_out = i;
++ return 0;
++ }
++ return 1;
++}
++
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned int i = 0;
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++asmlinkage void decompress_kernel(void *rmode, unsigned long end,
++ uch *input_data, unsigned long input_len, uch *output)
++{
++ real_mode = rmode;
++
++ if (RM_SCREEN_INFO.orig_video_mode == 7) {
++ vidmem = (char *) 0xb0000;
++ vidport = 0x3b4;
++ } else {
++ vidmem = (char *) 0xb8000;
++ vidport = 0x3d4;
++ }
++
++ lines = RM_SCREEN_INFO.orig_video_lines;
++ cols = RM_SCREEN_INFO.orig_video_cols;
++
++ window = output; /* Output buffer (Normally at 1M) */
++ free_mem_ptr = end; /* Heap */
++ free_mem_end_ptr = end + HEAP_SIZE;
++ inbuf = input_data; /* Input buffer */
++ insize = input_len;
++ inptr = 0;
++
++ if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
++ error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
++ if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
++ error("Destination address too large");
++#ifndef CONFIG_RELOCATABLE
++ if ((u32)output != LOAD_PHYSICAL_ADDR)
++ error("Wrong destination address");
++#endif
++ if( lzma_unzip(output) != 0 )
++ {
++ error("inflate error\n");
++ }
++ putstr("Ok, booting the kernel.\n");
++
++ return;
++}
+diff --git a/arch/i386/boot/compressed/vmlinux.scr b/arch/i386/boot/compressed/vmlinux.scr
+index 707a88f..9d67263 100644
+--- a/arch/i386/boot/compressed/vmlinux.scr
++++ b/arch/i386/boot/compressed/vmlinux.scr
+@@ -3,8 +3,8 @@ SECTIONS
+ .data.compressed : {
+ input_len = .;
+ LONG(input_data_end - input_data) input_data = .;
++ output_len = . + 5;
+ *(.data)
+- output_len = . - 4;
+ input_data_end = .;
+ }
+ }
+diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
+index 17ee97f..64b7bda 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -406,6 +406,47 @@ config BLK_DEV_RAM_BLOCKSIZE
+ setups function - apparently needed by the rd_load_image routine
+ that supposes the filesystem in the image uses a 1024 blocksize.
+
++config LZMA_INITRD
++ boolean "Allow LZMA compression on initrd"
++ depends on BLK_DEV_INITRD=y
++ default "y"
++ help
++ Use lzma compression on initrd, example 'lzma e initrd initrd.7z -d16'.
++ If you have sufficient memory, you could compress using bigger dictionary size,
++ 'lzma e initrd initrd.7z'.
++
++config LZMA_INITRD_KMALLOC_ONLY
++ boolean "Use only kmalloc, do not use vmalloc on lzma initrd"
++ depends on LZMA_INITRD=y
++ default "n"
++ help
++ Set to y if you do not want to use vmalloc, ie use only kmalloc.
++
++config LZMA_INITRAM_FS
++ boolean "Allow LZMA compression on initramfs"
++ depends on BLK_DEV_RAM=y
++ default "y"
++ help
++ Use lzma compression on initramfs, example 'lzma e initramfs.cpio initramfs.cpio.lzma'.
++
++config LZMA_INITRAM_FS_SMALLMEM
++ boolean "Use lzma compression with small dictonary size."
++ depends on LZMA_INITRAM_FS=y
++ default "y"
++ help
++ Use lzma compression on initramfs with small dictionary size, example
++ 'lzma e initramfs.cpio initramfs.cpio.lzma -d16'.
++ Affects only the initramfs.cpio in the ~usr directory, which is compiled into
++ the kernel. If you prepared initramfs.cpio for use with bootloader, you would
++ need to specify the commandline options (-d16) yourself.
++
++config LZMA_INITRAM_FS_KMALLOC_ONLY
++ boolean "Use only kmalloc, do not use vmalloc on lzma initramfs"
++ depends on LZMA_INITRAM_FS=y
++ default "n"
++ help
++ Set to y if you do not want to use vmalloc, ie use only kmalloc.
++
+ config CDROM_PKTCDVD
+ tristate "Packet writing on CD/DVD media"
+ depends on !UML
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 3c4886b..bdcc6fb 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -1371,6 +1371,71 @@ config CRAMFS
+
+ If unsure, say N.
+
++config SQUASHFS
++ tristate "SquashFS 3.2 - Squashed file system support"
++ select ZLIB_INFLATE
++ help
++ Saying Y here includes support for SquashFS 3.2 (a Compressed Read-Only File
++ System). Squashfs is a highly compressed read-only filesystem for Linux.
++ It uses zlib compression to compress both files, inodes and directories.
++ Inodes in the system are very small and all blocks are packed to minimise
++ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
++ SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full
++ uid/gid information, hard links and timestamps.
++
++ Squashfs is intended for general read-only filesystem use, for archival
++ use (i.e. in cases where a .tar.gz file may be used), and in embedded
++ systems where low overhead is needed. Further information and filesystem tools
++ are available from http://squashfs.sourceforge.net.
++
++ If you want to compile this as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called squashfs. Note that the root file system (the one
++ containing the directory /) cannot be compiled as a module.
++
++ If unsure, say N.
++
++config SQUASHFS_EMBEDDED
++
++ bool "Additional options for memory-constrained systems"
++ depends on SQUASHFS
++ default n
++ help
++ Saying Y here allows you to specify cache sizes and how Squashfs
++ allocates memory. This is only intended for memory constrained
++ systems.
++
++ If unsure, say N.
++
++config SQUASHFS_FRAGMENT_CACHE_SIZE
++ int "Number of fragments cached" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default "3"
++ help
++ By default SquashFS caches the last 3 fragments read from
++ the filesystem. Increasing this amount may mean SquashFS
++ has to re-read fragments less often from disk, at the expense
++ of extra system memory. Decreasing this amount will mean
++ SquashFS uses less memory at the expense of extra reads from disk.
++
++ Note there must be at least one cached fragment. Anything
++ much more than three will probably not make much difference.
++
++config SQUASHFS_VMALLOC
++ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default n
++ help
++ By default SquashFS uses kmalloc to obtain fragment cache memory.
++ Kmalloc memory is the standard kernel allocator, but it can fail
++ on memory constrained systems. Because of the way Vmalloc works,
++ Vmalloc can succeed when kmalloc fails. Specifying this option
++ will make SquashFS always use Vmalloc to allocate the
++ fragment cache memory.
++
++ If unsure, say N.
++
+ config VXFS_FS
+ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+ depends on BLOCK
+@@ -2057,3 +2122,4 @@ source "fs/dlm/Kconfig"
+
+ endmenu
+
++source "fs/aufs/Kconfig"
+diff --git a/fs/Makefile b/fs/Makefile
+index 9edf411..557766f 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -68,6 +68,7 @@ obj-$(CONFIG_JBD) += jbd/
+ obj-$(CONFIG_JBD2) += jbd2/
+ obj-$(CONFIG_EXT2_FS) += ext2/
+ obj-$(CONFIG_CRAMFS) += cramfs/
++obj-$(CONFIG_SQUASHFS) += squashfs/
+ obj-$(CONFIG_RAMFS) += ramfs/
+ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
+ obj-$(CONFIG_CODA_FS) += coda/
+@@ -114,3 +115,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
+ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_AUFS) += aufs/
+diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig
+new file mode 100644
+index 0000000..3a2121c
+--- /dev/null
++++ b/fs/aufs/Kconfig
+@@ -0,0 +1,73 @@
++config AUFS
++ tristate "Another unionfs"
++ help
++ Aufs is a stackable unification filesystem such as Unionfs,
++ which unifies several directories and provides a merged single
++ directory.
++ In the early days, aufs was entirely re-designed and
++ re-implemented Unionfs Version 1.x series. After many original
++ ideas, approaches and improvements, it becomes totally
++ different from Unionfs while keeping the basic features.
++ See Unionfs for the basic features.
++
++if AUFS
++comment "These options are generated automatically for "#UTS_RELEASE
++
++config AUFS_FAKE_DM
++ bool "Use simplified (fake) nameidata"
++ depends on AUFS
++ default y
++ help
++ Faking nameidata (VFS internal data), you can get better performance
++ in some cases.
++
++choice
++ prompt "Maximum number of branches"
++ depends on AUFS
++ default AUFS_BRANCH_MAX_127
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_127
++ bool "127"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_511
++ bool "511"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_1023
++ bool "1023"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++
++config AUFS_BRANCH_MAX_32767
++ bool "32767"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++endchoice
++config AUFS_DEBUG
++ bool "Debug aufs"
++ depends on AUFS
++ default y
++ help
++ Enable this to compile aufs internal debug code.
++ The performance will be damaged.
++
++config AUFS_COMPAT
++ bool "Compatibility with Unionfs (obsolete)"
++ depends on AUFS
++ default n
++ help
++ This makes aufs compatible with unionfs-style mount options and some
++ behaviours.
++ The dirs= mount option and =nfsro branch permission flag are always
++ interpreted as br: mount option and =ro flag respectively. The
++ 'debug', 'delete' and 'imap' mount options are ignored.
++ If you disable this option, you will get,
++ - aufs issues a warning about the ignored mount options
++ - the default branch permission flag is set. RW for the first branch,
++ and RO for the rests.
++ - the name of a internal file which represents the directory is
++ 'opaque', becomes '.wh..wh..opq'
++ - the 'diropq=w' mount option is set by default
++endif
+diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile
+new file mode 100755
+index 0000000..0ee3cd0
+--- /dev/null
++++ b/fs/aufs/Makefile
+@@ -0,0 +1,18 @@
++# AUFS Makefile for the Linux 2.6.16 and later
++# $Id: Makefile,v 1.29 2007/04/23 00:59:50 sfjro Exp $
++
++obj-$(CONFIG_AUFS) += aufs.o
++aufs-y := module.o super.o sbinfo.o xino.o \
++ branch.o cpup.o whout.o plink.o wkq.o dcsub.o vfsub.o \
++ opts.o \
++ dentry.o dinfo.o \
++ file.o f_op.o finfo.o \
++ dir.o vdir.o \
++ inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
++ misc.o
++#xattr.o
++aufs-$(CONFIG_AUFS_SYSAUFS) += sysaufs.o
++aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
++aufs-$(CONFIG_AUFS_EXPORT) += export.o
++#aufs-$(CONFIG_DEBUGFS) += dbgfs.o
++aufs-$(CONFIG_AUFS_DEBUG) += debug.o
+diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h
+new file mode 100755
+index 0000000..79b3b87
+--- /dev/null
++++ b/fs/aufs/aufs.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: aufs.h,v 1.24 2007/05/14 03:41:51 sfjro Exp $ */
++
++#ifndef __AUFS_H__
++#define __AUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/version.h>
++
++/* limited support before 2.6.16, curretly 2.6.15 only. */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++#define atomic_long_t atomic_t
++#define atomic_long_set atomic_set
++#define timespec_to_ns(ts) ({(long long)(ts)->tv_sec;})
++#define D_CHILD d_child
++#else
++#define D_CHILD d_u.d_child
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++#include "debug.h"
++
++#include "branch.h"
++#include "cpup.h"
++#include "dcsub.h"
++#include "dentry.h"
++#include "dir.h"
++#include "file.h"
++#include "inode.h"
++#include "misc.h"
++#include "module.h"
++#include "opts.h"
++#include "super.h"
++#include "sysaufs.h"
++#include "vfsub.h"
++#include "whout.h"
++#include "wkq.h"
++//#include "xattr.h"
++
++#if defined(CONFIG_AUFS_MODULE) && !defined(CONFIG_AUFS_KSIZE_PATCH)
++#define ksize(p) (-1U)
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_H__ */
+diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
+new file mode 100755
+index 0000000..f1ce008
+--- /dev/null
++++ b/fs/aufs/branch.c
+@@ -0,0 +1,818 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: branch.c,v 1.49 2007/05/14 03:38:23 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++static void free_branch(struct aufs_branch *br)
++{
++ TraceEnter();
++
++ if (br->br_xino)
++ fput(br->br_xino);
++ dput(br->br_wh);
++ dput(br->br_plink);
++ mntput(br->br_mnt);
++ DEBUG_ON(br_count(br) || atomic_read(&br->br_wh_running));
++ kfree(br);
++}
++
++/*
++ * frees all branches
++ */
++void free_branches(struct aufs_sbinfo *sbinfo)
++{
++ aufs_bindex_t bmax;
++ struct aufs_branch **br;
++
++ TraceEnter();
++ bmax = sbinfo->si_bend + 1;
++ br = sbinfo->si_branch;
++ while (bmax--)
++ free_branch(*br++);
++}
++
++/*
++ * find the index of a branch which is specified by @br_id.
++ */
++int find_brindex(struct super_block *sb, aufs_bindex_t br_id)
++{
++ aufs_bindex_t bindex, bend;
++
++ TraceEnter();
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (sbr_id(sb, bindex) == br_id)
++ return bindex;
++ return -1;
++}
++
++/*
++ * test if the @br is readonly or not.
++ */
++int br_rdonly(struct aufs_branch *br)
++{
++ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
++ || !br_writable(br->br_perm))
++ ? -EROFS : 0;
++}
++
++/*
++ * returns writable branch index, otherwise an error.
++ * todo: customizable writable-branch-policy
++ */
++static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
++{
++ int err;
++ aufs_bindex_t bindex, candidate;
++ struct super_block *sb;
++ struct dentry *parent, *hidden_parent;
++
++ err = bend;
++ sb = dentry->d_sb;
++ parent = dget_parent(dentry);
++#if 1 // branch policy
++ hidden_parent = au_h_dptr_i(parent, bend);
++ if (hidden_parent && !br_rdonly(stobr(sb, bend)))
++ goto out; /* success */
++#endif
++
++ candidate = -1;
++ for (bindex = dbstart(parent); bindex <= bend; bindex++) {
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ if (hidden_parent && !br_rdonly(stobr(sb, bindex))) {
++#if 0 // branch policy
++ if (candidate == -1)
++ candidate = bindex;
++ if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
++ return bindex;
++#endif
++ err = bindex;
++ goto out; /* success */
++ }
++ }
++#if 0 // branch policy
++ err = candidate;
++ if (candidate != -1)
++ goto out; /* success */
++#endif
++ err = -EROFS;
++
++ out:
++ dput(parent);
++ return err;
++}
++
++int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++
++ for (bindex = bend; bindex >= 0; bindex--)
++ if (!br_rdonly(stobr(sb, bindex)))
++ return bindex;
++ return -EROFS;
++}
++
++int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
++{
++ int err;
++
++ err = find_rw_parent(dentry, bend);
++ if (err >= 0)
++ return err;
++ return find_rw_br(dentry->d_sb, bend);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if two hidden_dentries have overlapping branches.
++ */
++//todo: try is_subdir()
++static int do_is_overlap(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ struct dentry *d;
++
++ d = hidden_d1;
++ do {
++ if (unlikely(d == hidden_d2))
++ return 1;
++ d = d->d_parent; // dget_parent()
++ } while (!IS_ROOT(d));
++
++ return (d == hidden_d2);
++}
++
++#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
++#include <linux/loop.h>
++static int is_overlap_loopback(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ struct inode *hidden_inode;
++ struct loop_device *l;
++
++ hidden_inode = hidden_d1->d_inode;
++ if (MAJOR(hidden_inode->i_sb->s_dev) != LOOP_MAJOR)
++ return 0;
++
++ l = hidden_inode->i_sb->s_bdev->bd_disk->private_data;
++ hidden_d1 = l->lo_backing_file->f_dentry;
++ if (unlikely(hidden_d1->d_sb == sb))
++ return 1;
++ return do_is_overlap(sb, hidden_d1, hidden_d2);
++}
++#else
++#define is_overlap_loopback(sb, hidden_d1, hidden_d2) 0
++#endif
++
++static int is_overlap(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ LKTRTrace("d1 %.*s, d2 %.*s\n", DLNPair(hidden_d1), DLNPair(hidden_d2));
++ if (unlikely(hidden_d1 == hidden_d2))
++ return 1;
++ return do_is_overlap(sb, hidden_d1, hidden_d2)
++ || do_is_overlap(sb, hidden_d2, hidden_d1)
++ || is_overlap_loopback(sb, hidden_d1, hidden_d2)
++ || is_overlap_loopback(sb, hidden_d2, hidden_d1);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int init_br_wh(struct super_block *sb, aufs_bindex_t bindex,
++ struct aufs_branch *br, int new_perm,
++ struct dentry *h_root, struct vfsmount *h_mnt)
++{
++ int err, old_perm;
++ struct inode *dir = sb->s_root->d_inode,
++ *h_dir = h_root->d_inode;
++ const int new = (bindex < 0);
++
++ LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
++
++ if (new)
++ hi_lock_parent(h_dir);
++ else
++ hdir_lock(h_dir, dir, bindex);
++
++ br_wh_write_lock(br);
++ old_perm = br->br_perm;
++ br->br_perm = new_perm;
++ err = init_wh(h_root, br, au_do_nfsmnt(h_mnt), sb);
++ br->br_perm = old_perm;
++ br_wh_write_unlock(br);
++
++ if (new)
++ i_unlock(h_dir);
++ else
++ hdir_unlock(h_dir, dir, bindex);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * returns a newly allocated branch. @new_nbranch is a number of branches
++ * after adding a branch.
++ */
++static struct aufs_branch *alloc_addbr(struct super_block *sb, int new_nbranch)
++{
++ struct aufs_branch **branchp, *add_branch;
++ int sz;
++ void *p;
++ struct dentry *root;
++ struct inode *inode;
++ struct aufs_hinode *hinodep;
++ struct aufs_hdentry *hdentryp;
++
++ LKTRTrace("new_nbranch %d\n", new_nbranch);
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ IiMustWriteLock(inode);
++
++ add_branch = kmalloc(sizeof(*add_branch), GFP_KERNEL);
++ //if (LktrCond) {kfree(add_branch); add_branch = NULL;}
++ if (unlikely(!add_branch))
++ goto out;
++
++ sz = sizeof(*branchp) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*branchp);
++ p = stosi(sb)->si_branch;
++ branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) branchp = NULL;
++ if (unlikely(!branchp))
++ goto out;
++ stosi(sb)->si_branch = branchp;
++
++ sz = sizeof(*hdentryp) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*hdentryp);
++ p = dtodi(root)->di_hdentry;
++ hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) hdentryp = NULL;
++ if (unlikely(!hdentryp))
++ goto out;
++ dtodi(root)->di_hdentry = hdentryp;
++
++ sz = sizeof(*hinodep) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*hinodep);
++ p = itoii(inode)->ii_hinode;
++ hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) hinodep = NULL; // unavailable test
++ if (unlikely(!hinodep))
++ goto out;
++ itoii(inode)->ii_hinode = hinodep;
++ return add_branch; /* success */
++
++ out:
++ kfree(add_branch);
++ TraceErr(-ENOMEM);
++ return ERR_PTR(-ENOMEM);
++}
++
++/*
++ * test if the branch permission is legal or not.
++ */
++static int test_br(struct super_block *sb, struct inode *inode, int brperm,
++ char *path)
++{
++ int err;
++
++ err = 0;
++ if (unlikely(br_writable(brperm) && IS_RDONLY(inode))) {
++ Err("write permission for readonly fs or inode, %s\n", path);
++ err = -EINVAL;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * retunrs,,,
++ * 0: success, the caller will add it
++ * plus: success, it is already unified, the caller should ignore it
++ * minus: error
++ */
++static int test_add(struct super_block *sb, struct opt_add *add, int remount)
++{
++ int err;
++ struct dentry *root;
++ struct inode *inode, *hidden_inode;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%s, remo%d\n", add->path, remount);
++
++ root = sb->s_root;
++ if (unlikely(au_find_dbindex(root, add->nd.dentry) != -1)) {
++ err = 1;
++ if (!remount) {
++ err = -EINVAL;
++ Err("%s duplicated\n", add->path);
++ }
++ goto out;
++ }
++
++ err = -ENOSPC; //-E2BIG;
++ bend = sbend(sb);
++ //if (LktrCond) bend = AUFS_BRANCH_MAX;
++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
++ || AUFS_BRANCH_MAX - 1 <= bend)) {
++ Err("number of branches exceeded %s\n", add->path);
++ goto out;
++ }
++
++ err = -EDOM;
++ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
++ Err("bad index %d\n", add->bindex);
++ goto out;
++ }
++
++ inode = add->nd.dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink)) {
++ Err("no existence %s\n", add->path);
++ goto out;
++ }
++
++ err = -EINVAL;
++ if (unlikely(inode->i_sb == sb)) {
++ Err("%s must be outside\n", add->path);
++ goto out;
++ }
++
++#if 1 //ndef CONFIG_AUFS_ROBR
++ if (unlikely(au_is_aufs(inode->i_sb)
++ || !strcmp(au_sbtype(inode->i_sb), "unionfs"))) {
++ Err("nested " AUFS_NAME " %s\n", add->path);
++ goto out;
++ }
++#endif
++
++#ifdef AuNoNfsBranch
++ if (unlikely(au_is_nfs(inode->i_sb))) {
++ Err(AuNoNfsBranchMsg ". %s\n", add->path);
++ goto out;
++ }
++#endif
++
++ err = test_br(sb, add->nd.dentry->d_inode, add->perm, add->path);
++ if (unlikely(err))
++ goto out;
++
++ if (unlikely(bend == -1))
++ return 0; /* success */
++
++ hidden_inode = au_h_dptr(root)->d_inode;
++ if (unlikely(au_flag_test(sb, AuFlag_WARN_PERM)
++ && ((hidden_inode->i_mode & S_IALLUGO)
++ != (inode->i_mode & S_IALLUGO)
++ || hidden_inode->i_uid != inode->i_uid
++ || hidden_inode->i_gid != inode->i_gid)))
++ Warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++ add->path,
++ inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
++ hidden_inode->i_uid, hidden_inode->i_gid,
++ (hidden_inode->i_mode & S_IALLUGO));
++
++ err = -EINVAL;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(is_overlap(sb, add->nd.dentry,
++ au_h_dptr_i(root, bindex)))) {
++ Err("%s is overlapped\n", add->path);
++ goto out;
++ }
++ err = 0;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int br_add(struct super_block *sb, struct opt_add *add, int remount)
++{
++ int err, sz;
++ aufs_bindex_t bend, add_bindex;
++ struct dentry *root;
++ struct aufs_iinfo *iinfo;
++ struct aufs_sbinfo *sbinfo;
++ struct aufs_dinfo *dinfo;
++ struct inode *root_inode;
++ unsigned long long maxb;
++ struct aufs_branch **branchp, *add_branch;
++ struct aufs_hdentry *hdentryp;
++ struct aufs_hinode *hinodep;
++
++ LKTRTrace("b%d, %s, 0x%x, %.*s\n", add->bindex, add->path,
++ add->perm, DLNPair(add->nd.dentry));
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ root_inode = root->d_inode;
++ IMustLock(root_inode);
++ IiMustWriteLock(root_inode);
++
++ err = test_add(sb, add, remount);
++ if (unlikely(err < 0))
++ goto out;
++ if (unlikely(err))
++ return 0; /* success */
++
++ bend = sbend(sb);
++ add_branch = alloc_addbr(sb, bend + 2);
++ err = PTR_ERR(add_branch);
++ if (IS_ERR(add_branch))
++ goto out;
++
++ err = 0;
++ rw_init_nolock(&add_branch->br_wh_rwsem);
++ add_branch->br_wh = add_branch->br_plink = NULL;
++ if (unlikely(br_writable(add->perm))) {
++ err = init_br_wh(sb, /*bindex*/-1, add_branch, add->perm,
++ add->nd.dentry, add->nd.mnt);
++ if (unlikely(err)) {
++ kfree(add_branch);
++ goto out;
++ }
++ }
++ add_branch->br_xino = NULL;
++ add_branch->br_mnt = mntget(add->nd.mnt);
++ atomic_set(&add_branch->br_wh_running, 0);
++ add_branch->br_id = new_br_id(sb);
++ add_branch->br_perm = add->perm;
++ atomic_set(&add_branch->br_count, 0);
++
++ sbinfo = stosi(sb);
++ dinfo = dtodi(root);
++ iinfo = itoii(root_inode);
++
++ add_bindex = add->bindex;
++ sz = sizeof(*(sbinfo->si_branch)) * (bend + 1 - add_bindex);
++ branchp = sbinfo->si_branch + add_bindex;
++ memmove(branchp + 1, branchp, sz);
++ *branchp = add_branch;
++ sz = sizeof(*hdentryp) * (bend + 1 - add_bindex);
++ hdentryp = dinfo->di_hdentry + add_bindex;
++ memmove(hdentryp + 1, hdentryp, sz);
++ hdentryp->hd_dentry = NULL;
++ sz = sizeof(*hinodep) * (bend + 1 - add_bindex);
++ hinodep = iinfo->ii_hinode + add_bindex;
++ memmove(hinodep + 1, hinodep, sz);
++ hinodep->hi_inode = NULL;
++ hinodep->hi_notify = NULL;
++
++ sbinfo->si_bend++;
++ dinfo->di_bend++;
++ iinfo->ii_bend++;
++ if (unlikely(bend == -1)) {
++ dinfo->di_bstart = 0;
++ iinfo->ii_bstart = 0;
++ }
++ set_h_dptr(root, add_bindex, dget(add->nd.dentry));
++ set_h_iptr(root_inode, add_bindex, igrab(add->nd.dentry->d_inode), 0);
++ if (!add_bindex)
++ au_cpup_attr_all(root_inode);
++ else
++ au_add_nlink(root_inode, add->nd.dentry->d_inode);
++ maxb = add->nd.dentry->d_sb->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++
++ if (au_flag_test(sb, AuFlag_XINO)) {
++ struct file *base_file = stobr(sb, 0)->br_xino;
++ if (!add_bindex)
++ base_file = stobr(sb, 1)->br_xino;
++ err = xino_init(sb, add_bindex, base_file, /*do_test*/1);
++ if (unlikely(err)) {
++ DEBUG_ON(add_branch->br_xino);
++ Err("ignored xino err %d, force noxino\n", err);
++ err = 0;
++ au_flag_clr(sb, AuFlag_XINO);
++ }
++ }
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the branch is deletable or not.
++ */
++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
++{
++ int err, i, j, sigen;
++ struct au_dcsub_pages dpages;
++
++ LKTRTrace("b%d\n", bindex);
++ SiMustWriteLock(root->d_sb);
++ DiMustWriteLock(root);
++
++ err = au_dpages_init(&dpages, GFP_KERNEL);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ sigen = au_sigen(root->d_sb);
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ struct au_dpage *dpage;
++ dpage = dpages.dpages + i;
++ for (j = 0; !err && j < dpage->ndentry; j++) {
++ struct dentry *d;
++
++ d = dpage->dentries[j];
++ if (au_digen(d) == sigen)
++ di_read_lock_child(d, AUFS_I_RLOCK);
++ else {
++ di_write_lock_child(d);
++ err = au_reval_dpath(d, sigen);
++ if (!err)
++ di_downgrade_lock(d, AUFS_I_RLOCK);
++ else {
++ di_write_unlock(d);
++ break;
++ }
++ }
++
++ if (au_h_dptr_i(d, bindex)
++ && (!S_ISDIR(d->d_inode->i_mode)
++ || dbstart(d) == dbend(d)))
++ err = -EBUSY;
++ di_read_unlock(d, AUFS_I_RLOCK);
++ if (err)
++ LKTRTrace("%.*s\n", DLNPair(d));
++ }
++ }
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int br_del(struct super_block *sb, struct opt_del *del, int remount)
++{
++ int err, do_wh, rerr;
++ struct dentry *root;
++ struct inode *inode, *hidden_dir;
++ aufs_bindex_t bindex, bend, br_id;
++ struct aufs_sbinfo *sbinfo;
++ struct aufs_dinfo *dinfo;
++ struct aufs_iinfo *iinfo;
++ struct aufs_branch *br;
++
++ LKTRTrace("%s, %.*s\n", del->path, DLNPair(del->h_root));
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ IiMustWriteLock(inode);
++
++ bindex = au_find_dbindex(root, del->h_root);
++ if (unlikely(bindex < 0)) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ Err("%s no such branch\n", del->path);
++ goto out;
++ }
++ LKTRTrace("bindex b%d\n", bindex);
++
++ err = -EBUSY;
++ bend = sbend(sb);
++ br = stobr(sb, bindex);
++ if (unlikely(!bend || br_count(br))) {
++ LKTRTrace("bend %d, br_count %d\n", bend, br_count(br));
++ goto out;
++ }
++
++ do_wh = 0;
++ hidden_dir = del->h_root->d_inode;
++ if (unlikely(br->br_wh || br->br_plink)) {
++#if 0
++ /* remove whiteout base */
++ err = init_br_wh(sb, bindex, br, AuBr_RO, del->h_root,
++ br->br_mnt);
++ if (unlikely(err))
++ goto out;
++#else
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++#endif
++ do_wh = 1;
++ }
++
++ err = test_children_busy(root, bindex);
++ if (unlikely(err)) {
++ if (unlikely(do_wh))
++ goto out_wh;
++ goto out;
++ }
++
++ err = 0;
++ sbinfo = stosi(sb);
++ dinfo = dtodi(root);
++ iinfo = itoii(inode);
++
++ dput(au_h_dptr_i(root, bindex));
++ aufs_hiput(iinfo->ii_hinode + bindex);
++ br_id = br->br_id;
++ free_branch(br);
++
++ //todo: realloc and shrink memeory
++ if (bindex < bend) {
++ const aufs_bindex_t n = bend - bindex;
++ struct aufs_branch **brp;
++ struct aufs_hdentry *hdp;
++ struct aufs_hinode *hip;
++
++ brp = sbinfo->si_branch + bindex;
++ memmove(brp, brp + 1, sizeof(*brp) * n);
++ hdp = dinfo->di_hdentry + bindex;
++ memmove(hdp, hdp + 1, sizeof(*hdp) * n);
++ hip = iinfo->ii_hinode + bindex;
++ memmove(hip, hip + 1, sizeof(*hip) * n);
++ }
++ sbinfo->si_branch[0 + bend] = NULL;
++ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
++ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
++ iinfo->ii_hinode[0 + bend].hi_notify = NULL;
++
++ sbinfo->si_bend--;
++ dinfo->di_bend--;
++ iinfo->ii_bend--;
++ if (!bindex)
++ au_cpup_attr_all(inode);
++ else
++ au_sub_nlink(inode, del->h_root->d_inode);
++ if (au_flag_test(sb, AuFlag_PLINK))
++ half_refresh_plink(sb, br_id);
++
++ if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
++ bend--;
++ sb->s_maxbytes = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ unsigned long long maxb;
++ maxb = sbr_sb(sb, bindex)->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++ }
++ }
++ goto out; /* success */
++
++ out_wh:
++ /* revert */
++ rerr = init_br_wh(sb, bindex, br, br->br_perm, del->h_root, br->br_mnt);
++ if (rerr)
++ Warn("failed re-creating base whiteout, %s. (%d)\n",
++ del->path, rerr);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int do_need_sigen_inc(int a, int b)
++{
++ return (br_whable(a) && !br_whable(b));
++}
++
++static int need_sigen_inc(int old, int new)
++{
++ return (do_need_sigen_inc(old, new)
++ || do_need_sigen_inc(new, old));
++}
++
++int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
++ int *do_update)
++{
++ int err;
++ struct dentry *root;
++ aufs_bindex_t bindex;
++ struct aufs_branch *br;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%s, %.*s, 0x%x\n",
++ mod->path, DLNPair(mod->h_root), mod->perm);
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ IiMustWriteLock(root->d_inode);
++
++ bindex = au_find_dbindex(root, mod->h_root);
++ if (unlikely(bindex < 0)) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ Err("%s no such branch\n", mod->path);
++ goto out;
++ }
++ LKTRTrace("bindex b%d\n", bindex);
++
++ hidden_dir = mod->h_root->d_inode;
++ err = test_br(sb, hidden_dir, mod->perm, mod->path);
++ if (unlikely(err))
++ goto out;
++
++ br = stobr(sb, bindex);
++ if (unlikely(br->br_perm == mod->perm))
++ return 0; /* success */
++
++ if (br_writable(br->br_perm)) {
++#if 1
++ /* remove whiteout base */
++ //todo: mod->perm?
++ err = init_br_wh(sb, bindex, br, AuBr_RO, mod->h_root,
++ br->br_mnt);
++ if (unlikely(err))
++ goto out;
++#else
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++#endif
++
++ if (!br_writable(mod->perm)) {
++ /* rw --> ro, file might be mmapped */
++ struct file *file, *hf;
++
++#if 1 // test here
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++
++ // no need file_list_lock() since sbinfo is locked
++ //file_list_lock();
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++ fi_read_lock(file);
++ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE)
++ || fbstart(file) != bindex) {
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ continue;
++ }
++
++ // todo: already flushed?
++ hf = au_h_fptr(file);
++ hf->f_flags = au_file_roflags(hf->f_flags);
++ hf->f_mode &= ~FMODE_WRITE;
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ }
++ //file_list_unlock();
++
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++#endif
++ }
++ }
++
++ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++ br->br_perm = mod->perm;
++ return err; /* success */
++
++ out:
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
+new file mode 100755
+index 0000000..2557836
+--- /dev/null
++++ b/fs/aufs/branch.h
+@@ -0,0 +1,235 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: branch.h,v 1.30 2007/05/14 03:41:51 sfjro Exp $ */
++
++#ifndef __AUFS_BRANCH_H__
++#define __AUFS_BRANCH_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "super.h"
++
++/* protected by superblock rwsem */
++struct aufs_branch {
++ struct file *br_xino;
++ readf_t br_xino_read;
++ writef_t br_xino_write;
++
++ aufs_bindex_t br_id;
++
++ int br_perm;
++ struct vfsmount *br_mnt;
++ atomic_t br_count;
++
++ /* whiteout base */
++ struct aufs_rwsem br_wh_rwsem;
++ struct dentry *br_wh;
++ atomic_t br_wh_running;
++
++ /* pseudo-link dir */
++ struct dentry *br_plink;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* branch permission and attribute */
++enum {
++ AuBr_RW, /* writable, linkable wh */
++ AuBr_RO, /* readonly, no wh */
++ AuBr_RR, /* natively readonly, no wh */
++
++ AuBr_RWNoLinkWH, /* un-linkable whiteouts */
++
++ AuBr_ROWH,
++ AuBr_RRWH, /* whiteout-able */
++
++ AuBr_Last
++};
++
++static inline int br_writable(int brperm)
++{
++ return (brperm == AuBr_RW
++ || brperm == AuBr_RWNoLinkWH);
++}
++
++static inline int br_whable(int brperm)
++{
++ return (brperm == AuBr_RW
++ || brperm == AuBr_ROWH
++ || brperm == AuBr_RRWH);
++}
++
++static inline int br_linkable_wh(int brperm)
++{
++ return (brperm == AuBr_RW);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define _AuNoNfsBranchMsg "NFS branch is not supported"
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,15)
++#define AuNoNfsBranch
++#define AuNoNfsBranchMsg _AuNoNfsBranchMsg
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) \
++ && !defined(CONFIG_AUFS_LHASH_PATCH)
++#define AuNoNfsBranch
++#define AuNoNfsBranchMsg _AuNoNfsBranchMsg \
++ ", try lhash.patch and CONFIG_AUFS_LHASH_PATCH"
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_sbinfo;
++void free_branches(struct aufs_sbinfo *sinfo);
++int br_rdonly(struct aufs_branch *br);
++int find_brindex(struct super_block *sb, aufs_bindex_t br_id);
++int find_rw_br(struct super_block *sb, aufs_bindex_t bend);
++int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend);
++struct opt_add;
++int br_add(struct super_block *sb, struct opt_add *add, int remount);
++struct opt_del;
++int br_del(struct super_block *sb, struct opt_del *del, int remount);
++struct opt_mod;
++int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
++ int *do_update);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int br_count(struct aufs_branch *br)
++{
++ return atomic_read(&br->br_count);
++}
++
++static inline void br_get(struct aufs_branch *br)
++{
++ atomic_inc(&br->br_count);
++}
++
++static inline void br_put(struct aufs_branch *br)
++{
++ atomic_dec(&br->br_count);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Superblock to branch */
++static inline aufs_bindex_t sbr_id(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_id;
++}
++
++static inline
++struct vfsmount *sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_mnt;
++}
++
++static inline
++struct super_block *sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return sbr_mnt(sb, bindex)->mnt_sb;
++}
++
++#if 0
++static inline int sbr_count(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return br_count(stobr(sb, bindex));
++}
++
++static inline void sbr_get(struct super_block *sb, aufs_bindex_t bindex)
++{
++ br_get(stobr(sb, bindex));
++}
++#endif
++
++static inline void sbr_put(struct super_block *sb, aufs_bindex_t bindex)
++{
++ br_put(stobr(sb, bindex));
++}
++
++static inline int sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_perm;
++}
++
++static inline int sbr_is_whable(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return br_whable(sbr_perm(sb, bindex));
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_LHASH_PATCH
++static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
++{
++ if (!au_is_nfs(h_mnt->mnt_sb))
++ return NULL;
++ return h_mnt;
++}
++
++/* it doesn't mntget() */
++static inline
++struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_do_nfsmnt(sbr_mnt(sb, bindex));
++}
++#else
++static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
++{
++ return NULL;
++}
++
++static inline
++struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return NULL;
++}
++#endif /* CONFIG_AUFS_LHASH_PATCH */
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * br_wh_read_lock, br_wh_write_lock
++ * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
++ */
++SimpleRwsemFuncs(br_wh, struct aufs_branch *br, br->br_wh_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define BrWhMustReadLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustReadLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#define BrWhMustWriteLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustWriteLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#define BrWhMustAnyLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustAnyLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_BRANCH_H__ */
+diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
+new file mode 100755
+index 0000000..6636f40
+--- /dev/null
++++ b/fs/aufs/cpup.c
+@@ -0,0 +1,773 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: cpup.c,v 1.37 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++/* violent cpup_attr_*() functions don't care inode lock */
++void au_cpup_attr_timesizes(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++ //IMustLock(!hidden_inode);
++
++ inode->i_atime = hidden_inode->i_atime;
++ inode->i_mtime = hidden_inode->i_mtime;
++ inode->i_ctime = hidden_inode->i_ctime;
++ spin_lock(&inode->i_lock);
++ i_size_write(inode, i_size_read(hidden_inode));
++ inode->i_blocks = hidden_inode->i_blocks;
++ spin_unlock(&inode->i_lock);
++}
++
++void au_cpup_attr_nlink(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ DEBUG_ON(!inode->i_mode);
++
++ h_inode = au_h_iptr(inode);
++ inode->i_nlink = h_inode->i_nlink;
++
++ /*
++ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
++ * it may includes whplink directory.
++ */
++ if (unlikely(S_ISDIR(h_inode->i_mode))) {
++ aufs_bindex_t bindex, bend;
++ bend = ibend(inode);
++ for (bindex = ibstart(inode) + 1; bindex <= bend; bindex++) {
++ h_inode = au_h_iptr_i(inode, bindex);
++ if (h_inode)
++ au_add_nlink(inode, h_inode);
++ }
++ }
++}
++
++void au_cpup_attr_changable(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++
++ inode->i_mode = hidden_inode->i_mode;
++ inode->i_uid = hidden_inode->i_uid;
++ inode->i_gid = hidden_inode->i_gid;
++ au_cpup_attr_timesizes(inode);
++
++ //??
++ inode->i_flags = hidden_inode->i_flags;
++}
++
++void au_cpup_igen(struct inode *inode, struct inode *h_inode)
++{
++ inode->i_generation = h_inode->i_generation;
++ itoii(inode)->ii_hsb1 = h_inode->i_sb;
++}
++
++void au_cpup_attr_all(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++
++ au_cpup_attr_changable(inode);
++ if (inode->i_nlink > 0)
++ au_cpup_attr_nlink(inode);
++
++ switch (inode->i_mode & S_IFMT) {
++ case S_IFBLK:
++ case S_IFCHR:
++ inode->i_rdev = hidden_inode->i_rdev;
++ }
++ inode->i_blkbits = hidden_inode->i_blkbits;
++ au_cpup_attr_blksize(inode, hidden_inode);
++ au_cpup_igen(inode, hidden_inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
++
++/* keep the timestamps of the parent dir when cpup */
++void dtime_store(struct dtime *dt, struct dentry *dentry,
++ struct dentry *hidden_dentry)
++{
++ struct inode *inode;
++
++ TraceEnter();
++ DEBUG_ON(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
++
++ dt->dt_dentry = dentry;
++ dt->dt_h_dentry = hidden_dentry;
++ inode = hidden_dentry->d_inode;
++ dt->dt_atime = inode->i_atime;
++ dt->dt_mtime = inode->i_mtime;
++ //smp_mb();
++}
++
++// todo: remove extra parameter
++void dtime_revert(struct dtime *dt, int h_parent_is_locked)
++{
++ struct iattr attr;
++ int err;
++ struct dentry *dentry;
++
++ LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
++
++ attr.ia_atime = dt->dt_atime;
++ attr.ia_mtime = dt->dt_mtime;
++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
++ | ATTR_ATIME | ATTR_ATIME_SET;
++ //smp_mb();
++ dentry = NULL;
++ if (!h_parent_is_locked /* && !IS_ROOT(dt->dt_dentry) */)
++ dentry = dt->dt_dentry;
++ err = vfsub_notify_change(dt->dt_h_dentry, &attr,
++ need_dlgt(dt->dt_dentry->d_sb));
++ if (unlikely(err))
++ Warn("restoring timestamps failed(%d). ignored\n", err);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
++ int dlgt)
++{
++ int err;
++ struct iattr ia;
++ struct inode *hidden_isrc, *hidden_idst;
++
++ LKTRTrace("%.*s\n", DLNPair(hidden_dst));
++ hidden_idst = hidden_dst->d_inode;
++ //IMustLock(hidden_idst);
++ hidden_isrc = hidden_src->d_inode;
++ //IMustLock(hidden_isrc);
++
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
++ | ATTR_ATIME | ATTR_MTIME
++ | ATTR_ATIME_SET | ATTR_MTIME_SET;
++ ia.ia_mode = hidden_isrc->i_mode;
++ ia.ia_uid = hidden_isrc->i_uid;
++ ia.ia_gid = hidden_isrc->i_gid;
++ ia.ia_atime = hidden_isrc->i_atime;
++ ia.ia_mtime = hidden_isrc->i_mtime;
++ err = vfsub_notify_change(hidden_dst, &ia, dlgt);
++ //if (LktrCond) err = -1;
++ if (!err)
++ hidden_idst->i_flags = hidden_isrc->i_flags; //??
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * to support a sparse file which is opened with O_APPEND,
++ * we need to close the file.
++ */
++static int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len)
++{
++ int err, i, sparse;
++ struct super_block *sb;
++ struct inode *hidden_inode;
++ enum {SRC, DST};
++ struct {
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ struct dentry *dentry;
++ struct file *file;
++ void *label, *label_file;
++ } *h, hidden[] = {
++ {
++ .bindex = bsrc,
++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out,
++ .label_file = &&out_src_file
++ },
++ {
++ .bindex = bdst,
++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out_src_file,
++ .label_file = &&out_dst_file
++ }
++ };
++
++ LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
++ DLNPair(dentry), bdst, bsrc, len);
++ DEBUG_ON(bsrc <= bdst);
++ DEBUG_ON(!len);
++ sb = dentry->d_sb;
++ DEBUG_ON(test_ro(sb, bdst, dentry->d_inode));
++ // bsrc branch can be ro/rw.
++
++ h = hidden;
++ for (i = 0; i < 2; i++, h++) {
++ h->dentry = au_h_dptr_i(dentry, h->bindex);
++ DEBUG_ON(!h->dentry);
++ hidden_inode = h->dentry->d_inode;
++ DEBUG_ON(!hidden_inode || !S_ISREG(hidden_inode->i_mode));
++ h->file = hidden_open(dentry, h->bindex, h->flags);
++ //if (LktrCond)
++ //{fput(h->file); sbr_put(sb, h->bindex); h->file = ERR_PTR(-1);}
++ err = PTR_ERR(h->file);
++ if (IS_ERR(h->file))
++ goto *h->label;
++ err = -EINVAL;
++ if (unlikely(!h->file->f_op))
++ goto *h->label_file;
++ }
++
++ /* stop updating while we copyup */
++ IMustLock(hidden[SRC].dentry->d_inode);
++ sparse = 0;
++ err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb,
++ &sparse);
++
++ /* sparse file: update i_blocks next time */
++ if (unlikely(!err && sparse))
++ d_drop(dentry);
++
++ out_dst_file:
++ fput(hidden[DST].file);
++ sbr_put(sb, hidden[DST].bindex);
++ out_src_file:
++ fput(hidden[SRC].file);
++ sbr_put(sb, hidden[SRC].bindex);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++// unnecessary?
++unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
++{
++ if (unlikely(parent && IS_ROOT(parent)))
++ init |= CPUP_LOCKED_GHDIR;
++ return init;
++}
++
++/* return with hidden dst inode is locked */
++static int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ int dlgt)
++{
++ int err, isdir, symlen;
++ struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
++ struct inode *hidden_inode, *hidden_dir, *dir;
++ struct dtime dt;
++ umode_t mode;
++ char *sym;
++ mm_segment_t old_fs;
++ const int do_dt = flags & CPUP_DTIME;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++ sb = dentry->d_sb;
++ DEBUG_ON(bdst >= bsrc || test_ro(sb, bdst, NULL));
++ // bsrc branch can be ro/rw.
++
++ hidden_src = au_h_dptr_i(dentry, bsrc);
++ DEBUG_ON(!hidden_src);
++ hidden_inode = hidden_src->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ /* stop refrencing while we are creating */
++ //parent = dget_parent(dentry);
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ hidden_dst = au_h_dptr_i(dentry, bdst);
++ DEBUG_ON(hidden_dst && hidden_dst->d_inode);
++ //hidden_parent = dget_parent(hidden_dst);
++ hidden_parent = hidden_dst->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ if (do_dt)
++ dtime_store(&dt, parent, hidden_parent);
++
++ isdir = 0;
++ mode = hidden_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ /* stop updating while we are referencing */
++ IMustLock(hidden_inode);
++ err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
++ dlgt);
++ //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ if (!err) {
++ loff_t l = i_size_read(hidden_inode);
++ if (len == -1 || l < len)
++ len = l;
++ if (len) {
++ err = cpup_regular(dentry, bdst, bsrc, len);
++ //if (LktrCond) err = -1;
++ }
++ if (unlikely(err)) {
++ int rerr;
++ rerr = vfsub_unlink(hidden_dir, hidden_dst,
++ dlgt);
++ if (rerr) {
++ IOErr("failed unlinking cpup-ed %.*s"
++ "(%d, %d)\n",
++ DLNPair(hidden_dst), err, rerr);
++ err = -EIO;
++ }
++ }
++ }
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ err = vfsub_mkdir(hidden_dir, hidden_dst, mode, dlgt);
++ //if (LktrCond) {vfs_rmdir(hidden_dir, hidden_dst); err = -1;}
++ if (!err) {
++ /* setattr case: dir is not locked */
++ if (0 && ibstart(dir) == bdst)
++ au_cpup_attr_nlink(dir);
++ au_cpup_attr_nlink(dentry->d_inode);
++ }
++ break;
++ case S_IFLNK:
++ err = -ENOMEM;
++ sym = __getname();
++ //if (LktrCond) {__putname(sym); sym = NULL;}
++ if (unlikely(!sym))
++ break;
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = symlen = hidden_inode->i_op->readlink
++ (hidden_src, (char __user*)sym, PATH_MAX);
++ //if (LktrCond) err = symlen = -1;
++ set_fs(old_fs);
++ if (symlen > 0) {
++ sym[symlen] = 0;
++ err = vfsub_symlink(hidden_dir, hidden_dst, sym, mode,
++ dlgt);
++ //if (LktrCond)
++ //{vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ }
++ __putname(sym);
++ break;
++ case S_IFCHR:
++ case S_IFBLK:
++ DEBUG_ON(!capable(CAP_MKNOD));
++ /*FALLTHROUGH*/
++ case S_IFIFO:
++ case S_IFSOCK:
++ err = vfsub_mknod(hidden_dir, hidden_dst, mode,
++ hidden_inode->i_rdev, dlgt);
++ //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ break;
++ default:
++ IOErr("Unknown inode type 0%o\n", mode);
++ err = -EIO;
++ }
++
++ if (do_dt)
++ dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
++ //dput(parent);
++ //dput(hidden_parent);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the @dentry from @bsrc to @bdst.
++ * the caller must set the both of hidden dentries.
++ * @len is for trucating when it is -1 copyup the entire file.
++ */
++int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
++ loff_t len, unsigned int flags)
++{
++ int err, rerr, isdir, dlgt;
++ struct dentry *hidden_src, *hidden_dst, *parent;//, *h_parent;
++ struct inode *dst_inode, *hidden_dir, *inode, *src_inode;
++ struct super_block *sb;
++ aufs_bindex_t old_ibstart;
++ struct dtime dt;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++ sb = dentry->d_sb;
++ DEBUG_ON(bsrc <= bdst);
++ hidden_dst = au_h_dptr_i(dentry, bdst);
++ DEBUG_ON(!hidden_dst || hidden_dst->d_inode);
++ //h_parent = dget_parent(hidden_dst);
++ //hidden_dir = h_parent->d_inode;
++ hidden_dir = hidden_dst->d_parent->d_inode;
++ IMustLock(hidden_dir);
++ hidden_src = au_h_dptr_i(dentry, bsrc);
++ DEBUG_ON(!hidden_src || !hidden_src->d_inode);
++ inode = dentry->d_inode;
++ IiMustWriteLock(inode);
++
++ dlgt = need_dlgt(sb);
++ dst_inode = au_h_iptr_i(inode, bdst);
++ if (unlikely(dst_inode)) {
++ if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
++ err = -EIO;
++ IOErr("i%lu exists on a upper branch "
++ "but plink is disabled\n", inode->i_ino);
++ goto out;
++ }
++
++ if (dst_inode->i_nlink) {
++ hidden_src = lkup_plink(sb, bdst, inode);
++ err = PTR_ERR(hidden_src);
++ if (IS_ERR(hidden_src))
++ goto out;
++ DEBUG_ON(!hidden_src->d_inode);
++ // vfs_link() does lock the inode
++ err = vfsub_link(hidden_src, hidden_dir, hidden_dst, dlgt);
++ dput(hidden_src);
++ goto out;
++ } else
++ /* udba work */
++ au_update_brange(inode, 1);
++ }
++
++ old_ibstart = ibstart(inode);
++ err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
++ if (unlikely(err))
++ goto out;
++ dst_inode = hidden_dst->d_inode;
++ hi_lock_child2(dst_inode);
++
++ //todo: test dlgt
++ err = cpup_iattr(hidden_dst, hidden_src, dlgt);
++ //if (LktrCond) err = -1;
++#if 0 // xattr
++ if (0 && !err)
++ err = cpup_xattrs(hidden_src, hidden_dst);
++#endif
++ isdir = S_ISDIR(dst_inode->i_mode);
++ if (!err) {
++ if (bdst < old_ibstart)
++ set_ibstart(inode, bdst);
++ set_h_iptr(inode, bdst, igrab(dst_inode),
++ au_hi_flags(inode, isdir));
++ i_unlock(dst_inode);
++ src_inode = hidden_src->d_inode;
++ if (!isdir) {
++ if (src_inode->i_nlink > 1
++ && au_flag_test(sb, AuFlag_PLINK))
++ append_plink(sb, inode, hidden_dst, bdst);
++ else {
++ /* braces are added to stop a warning */
++ ;//xino_write0(sb, bsrc, src_inode->i_ino);
++ /* ignore this error */
++ }
++ }
++ //goto out; /* success */
++ return 0; /* success */
++ }
++
++ /* revert */
++ i_unlock(dst_inode);
++ parent = dget_parent(dentry);
++ //dtime_store(&dt, parent, h_parent);
++ dtime_store(&dt, parent, hidden_dst->d_parent);
++ dput(parent);
++ if (!isdir)
++ rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
++ else
++ rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
++ //rerr = -1;
++ dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
++ if (rerr) {
++ IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ //dput(h_parent);
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_single_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst, bsrc;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void call_cpup_single(void *args)
++{
++ struct cpup_single_args *a = args;
++ *a->errp = cpup_single(a->dentry, a->bdst, a->bsrc, a->len, a->flags);
++}
++
++int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags)
++{
++ int err;
++ struct dentry *hidden_dentry;
++ umode_t mode;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++
++ hidden_dentry = au_h_dptr_i(dentry, bsrc);
++ mode = hidden_dentry->d_inode->i_mode & S_IFMT;
++ if ((mode != S_IFCHR && mode != S_IFBLK)
++ || capable(CAP_MKNOD))
++ err = cpup_single(dentry, bdst, bsrc, len, flags);
++ else {
++ struct cpup_single_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .bsrc = bsrc,
++ .len = len,
++ .flags = flags
++ };
++ au_wkq_wait(call_cpup_single, &args, /*dlgt*/0);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the @dentry from the first active hidden branch to @bdst,
++ * using cpup_single().
++ */
++int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err;
++ struct inode *inode;
++ aufs_bindex_t bsrc, bend;
++
++ LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), bdst, len, flags);
++ inode = dentry->d_inode;
++ DEBUG_ON(!S_ISDIR(inode->i_mode) && dbstart(dentry) < bdst);
++
++ bend = dbend(dentry);
++ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
++ if (au_h_dptr_i(dentry, bsrc))
++ break;
++ DEBUG_ON(!au_h_dptr_i(dentry, bsrc));
++
++ err = lkup_neg(dentry, bdst);
++ //err = -1;
++ if (!err) {
++ err = cpup_single(dentry, bdst, bsrc, len, flags);
++ if (!err)
++ return 0; /* success */
++
++ /* revert */
++ set_h_dptr(dentry, bdst, NULL);
++ set_dbstart(dentry, bsrc);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_simple_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void call_cpup_simple(void *args)
++{
++ struct cpup_simple_args *a = args;
++ *a->errp = cpup_simple(a->dentry, a->bdst, a->len, a->flags);
++}
++
++int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err, do_sio, dlgt;
++ //struct dentry *parent;
++ struct inode *hidden_dir, *dir;
++
++ LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), bdst, len, flags);
++
++ //parent = dget_parent(dentry);
++ //dir = parent->d_inode;
++ dir = dentry->d_parent->d_inode;
++ hidden_dir = au_h_iptr_i(dir, bdst);
++ dlgt = need_dlgt(dir->i_sb);
++ do_sio = au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, dlgt);
++ if (!do_sio) {
++ umode_t mode = dentry->d_inode->i_mode & S_IFMT;
++ do_sio = ((mode == S_IFCHR || mode == S_IFBLK)
++ && !capable(CAP_MKNOD));
++ }
++ if (!do_sio)
++ err = cpup_simple(dentry, bdst, len, flags);
++ else {
++ struct cpup_simple_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .flags = flags
++ };
++ au_wkq_wait(call_cpup_simple, &args, /*dlgt*/0);
++ }
++
++ //dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++//todo: dcsub
++/* cf. revalidate function in file.c */
++int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *d, *parent, *hidden_parent;
++ unsigned int udba;
++
++ LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
++ DLNPair(dentry), bdst, parent_ino(dentry), locked);
++ sb = dentry->d_sb;
++ DEBUG_ON(test_ro(sb, bdst, NULL));
++ parent = dentry->d_parent;
++ IiMustWriteLock(parent->d_inode);
++ if (unlikely(IS_ROOT(parent)))
++ return 0;
++ if (locked) {
++ DiMustAnyLock(locked);
++ IiMustAnyLock(locked->d_inode);
++ }
++
++ /* slow loop, keep it simple and stupid */
++ err = 0;
++ udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++ while (1) {
++ parent = dentry->d_parent; // dget_parent()
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ if (hidden_parent)
++ return 0; /* success */
++
++ /* find top dir which is needed to cpup */
++ do {
++ d = parent;
++ parent = d->d_parent; // dget_parent()
++ if (parent != locked)
++ di_read_lock_parent3(parent, !AUFS_I_RLOCK);
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ if (parent != locked)
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ } while (!hidden_parent);
++
++ if (d != dentry->d_parent)
++ di_write_lock_child3(d);
++
++ /* somebody else might create while we were sleeping */
++ if (!au_h_dptr_i(d, bdst) || !au_h_dptr_i(d, bdst)->d_inode) {
++ struct inode *h_dir = hidden_parent->d_inode,
++ *dir = parent->d_inode,
++ *h_gdir, *gdir;
++
++ if (au_h_dptr_i(d, bdst))
++ au_update_dbstart(d);
++ //DEBUG_ON(dbstart(d) <= bdst);
++ if (parent != locked)
++ di_read_lock_parent3(parent, AUFS_I_RLOCK);
++ h_gdir = gdir = NULL;
++ if (unlikely(udba && !IS_ROOT(parent))) {
++ gdir = parent->d_parent->d_inode;
++ h_gdir = hidden_parent->d_parent->d_inode;
++ hgdir_lock(h_gdir, gdir, bdst);
++ }
++ hdir_lock(h_dir, dir, bdst);
++ err = sio_cpup_simple(d, bdst, -1,
++ au_flags_cpup(CPUP_DTIME,
++ parent));
++ //if (LktrCond) err = -1;
++ hdir_unlock(h_dir, dir, bdst);
++ if (unlikely(gdir))
++ hdir_unlock(h_gdir, gdir, bdst);
++ if (parent != locked)
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++
++ if (d != dentry->d_parent)
++ di_write_unlock(d);
++ if (unlikely(err))
++ break;
++ }
++
++// out:
++ TraceErr(err);
++ return err;
++}
++
++int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *locked)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *dir;
++
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
++ DLNPair(dentry), bdst, dir->i_ino, locked);
++ DiMustReadLock(parent);
++ IiMustReadLock(dir);
++
++ if (au_h_iptr_i(dir, bdst))
++ return 0;
++
++ err = 0;
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ di_write_lock_parent(parent);
++ if (au_h_iptr_i(dir, bdst))
++ goto out;
++
++ err = cpup_dirs(dentry, bdst, locked);
++
++ out:
++ di_downgrade_lock(parent, AUFS_I_RLOCK);
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h
+new file mode 100755
+index 0000000..86557aa
+--- /dev/null
++++ b/fs/aufs/cpup.h
+@@ -0,0 +1,72 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: cpup.h,v 1.15 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_CPUP_H__
++#define __AUFS_CPUP_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++static inline
++void au_cpup_attr_blksize(struct inode *inode, struct inode *h_inode)
++{
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++ inode->i_blksize = h_inode->i_blksize;
++#endif
++}
++
++void au_cpup_attr_timesizes(struct inode *inode);
++void au_cpup_attr_nlink(struct inode *inode);
++void au_cpup_attr_changable(struct inode *inode);
++void au_cpup_igen(struct inode *inode, struct inode *h_inode);
++void au_cpup_attr_all(struct inode *inode);
++
++#define CPUP_DTIME 1 // do dtime_store/revert
++// todo: remove this
++#define CPUP_LOCKED_GHDIR 2 // grand parent hidden dir is locked
++unsigned int au_flags_cpup(unsigned int init, struct dentry *parent);
++
++int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
++ loff_t len, unsigned int flags);
++int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags);
++int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++
++int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked);
++int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *locked);
++
++/* keep timestamps when copyup */
++struct dtime {
++ struct dentry *dt_dentry, *dt_h_dentry;
++ struct timespec dt_atime, dt_mtime;
++};
++void dtime_store(struct dtime *dt, struct dentry *dentry,
++ struct dentry *h_dentry);
++void dtime_revert(struct dtime *dt, int h_parent_is_locked);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_CPUP_H__ */
+diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
+new file mode 100755
+index 0000000..6ec29d3
+--- /dev/null
++++ b/fs/aufs/dcsub.c
+@@ -0,0 +1,175 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dcsub.c,v 1.3 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static void au_dpage_free(struct au_dpage *dpage)
++{
++ int i;
++
++ TraceEnter();
++ DEBUG_ON(!dpage);
++
++ for (i = 0; i < dpage->ndentry; i++)
++ dput(dpage->dentries[i]);
++ free_page((unsigned long)dpage->dentries);
++}
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
++{
++ int err;
++ void *p;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
++ if (unlikely(!dpages->dpages))
++ goto out;
++ p = (void*)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out_dpages;
++ dpages->dpages[0].ndentry = 0;
++ dpages->dpages[0].dentries = p;
++ dpages->ndpage = 1;
++ return 0; /* success */
++
++ out_dpages:
++ kfree(dpages->dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++void au_dpages_free(struct au_dcsub_pages *dpages)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < dpages->ndpage; i++)
++ au_dpage_free(dpages->dpages + i);
++ kfree(dpages->dpages);
++}
++
++static int au_dpages_append(struct au_dcsub_pages *dpages,
++ struct dentry *dentry, gfp_t gfp)
++{
++ int err, sz;
++ struct au_dpage *dpage;
++ void *p;
++
++ //TraceEnter();
++
++ dpage = dpages->dpages + dpages->ndpage - 1;
++ DEBUG_ON(!dpage);
++ sz = PAGE_SIZE/sizeof(dentry);
++ if (unlikely(dpage->ndentry >= sz)) {
++ LKTRLabel(new dpage);
++ err = -ENOMEM;
++ sz = dpages->ndpage * sizeof(*dpages->dpages);
++ p = au_kzrealloc(dpages->dpages, sz,
++ sz + sizeof(*dpages->dpages), gfp);
++ if (unlikely(!p))
++ goto out;
++ dpage = dpages->dpages + dpages->ndpage;
++ p = (void*)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out;
++ dpage->ndentry = 0;
++ dpage->dentries = p;
++ dpages->ndpage++;
++ }
++
++ dpage->dentries[dpage->ndentry++] = dget(dentry);
++ return 0; /* success */
++
++ out:
++ //TraceErr(err);
++ return err;
++}
++
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg)
++{
++ int err;
++ struct dentry *this_parent = root;
++ struct list_head *next;
++ struct super_block *sb = root->d_sb;
++
++ TraceEnter();
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ repeat:
++ next = this_parent->d_subdirs.next;
++ resume:
++ if (this_parent->d_sb == sb
++ && !IS_ROOT(this_parent)
++ && atomic_read(&this_parent->d_count)
++ && this_parent->d_inode
++ && (!test || test(this_parent, arg))) {
++ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++
++ while (next != &this_parent->d_subdirs) {
++ struct list_head *tmp = next;
++ struct dentry *dentry = list_entry(tmp, struct dentry, D_CHILD);
++ next = tmp->next;
++ if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode))
++ continue;
++ if (!list_empty(&dentry->d_subdirs)) {
++ this_parent = dentry;
++ goto repeat;
++ }
++ if (dentry->d_sb == sb
++ && atomic_read(&dentry->d_count)
++ && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ }
++
++ if (this_parent != root) {
++ next = this_parent->D_CHILD.next;
++ this_parent = this_parent->d_parent;
++ goto resume;
++ }
++ out:
++ spin_unlock(&dcache_lock);
++#if 0
++ if (!err) {
++ int i, j;
++ j = 0;
++ for (i = 0; i < dpages->ndpage; i++) {
++ if ((dpages->dpages + i)->ndentry)
++ Dbg("%d: %d\n", i, (dpages->dpages + i)->ndentry);
++ j += (dpages->dpages + i)->ndentry;
++ }
++ if (j)
++ Dbg("ndpage %d, %d\n", dpages->ndpage, j);
++ }
++#endif
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
+new file mode 100755
+index 0000000..0ba034b
+--- /dev/null
++++ b/fs/aufs/dcsub.h
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dcsub.h,v 1.2 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DCSUB_H__
++#define __AUFS_DCSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/dcache.h>
++
++struct au_dpage {
++ int ndentry;
++ struct dentry **dentries;
++};
++
++struct au_dcsub_pages {
++ int ndpage;
++ struct au_dpage *dpages;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
++void au_dpages_free(struct au_dcsub_pages *dpages);
++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DCSUB_H__ */
+diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
+new file mode 100755
+index 0000000..99d158b
+--- /dev/null
++++ b/fs/aufs/debug.c
+@@ -0,0 +1,262 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: debug.c,v 1.27 2007/04/30 05:48:23 sfjro Exp $ */
++
++#include "aufs.h"
++
++atomic_t aufs_cond = ATOMIC_INIT(0);
++
++#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
++#define dpri(fmt, arg...) \
++ do {if (LktrCond) printk(KERN_DEBUG fmt, ##arg);} while (0)
++#else
++#define dpri(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++void au_dpri_whlist(struct aufs_nhash *whlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ dpri("b%d, %.*s, %d\n",
++ tpos->wh_bindex,
++ tpos->wh_str.len, tpos->wh_str.name,
++ tpos->wh_str.len);
++ }
++}
++
++void au_dpri_vdir(struct aufs_vdir *vdir)
++{
++ int i;
++ union aufs_deblk_p p;
++ unsigned char *o;
++
++ if (!vdir || IS_ERR(vdir)) {
++ dpri("err %ld\n", PTR_ERR(vdir));
++ return;
++ }
++
++ dpri("nblk %d, deblk %p %d, last{%d, %p}, ver %lu\n",
++ vdir->vd_nblk, vdir->vd_deblk, ksize(vdir->vd_deblk),
++ vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
++ for (i = 0; i < vdir->vd_nblk; i++) {
++ p.deblk = vdir->vd_deblk[i];
++ o = p.p;
++ dpri("[%d]: %p %d\n", i, o, ksize(o));
++#if 0 // verbose
++ int j;
++ for (j = 0; j < 8; j++) {
++ dpri("%p(+%d) {%02x %02x %02x %02x %02x %02x %02x %02x "
++ "%02x %02x %02x %02x %02x %02x %02x %02x}\n",
++ p.p, p.p - o,
++ p.p[0], p.p[1], p.p[2], p.p[3],
++ p.p[4], p.p[5], p.p[6], p.p[7],
++ p.p[8], p.p[9], p.p[10], p.p[11],
++ p.p[12], p.p[13], p.p[14], p.p[15]);
++ p.p += 16;
++ }
++#endif
++ }
++}
++
++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode)
++{
++ if (!inode || IS_ERR(inode)) {
++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
++ return -1;
++ }
++
++ /* the type of i_blocks depends upon CONFIG_LSF */
++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
++ && sizeof(inode->i_blocks) != sizeof(u64));
++ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %Lu, blk %Lu,"
++ " ct %Ld, np %lu, st 0x%lx, g %x\n",
++ bindex,
++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
++ i_size_read(inode), (u64)inode->i_blocks,
++ timespec_to_ns(&inode->i_ctime) & 0x0ffff,
++ inode->i_mapping ? inode->i_mapping->nrpages : 0,
++ inode->i_state, inode->i_generation);
++ return 0;
++}
++
++void au_dpri_inode(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_inode(-1, inode);
++ if (err || !au_is_aufs(inode->i_sb))
++ return;
++
++ iinfo = itoii(inode);
++ if (!iinfo)
++ return;
++ dpri("i-1: bstart %d, bend %d, gen %d\n",
++ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
++ if (iinfo->ii_bstart < 0)
++ return;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
++ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode);
++}
++
++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
++{
++ if (!dentry || IS_ERR(dentry)) {
++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
++ return -1;
++ }
++ dpri("d%d: %.*s/%.*s, %s, cnt %d, flags 0x%x\n",
++ bindex,
++ DLNPair(dentry->d_parent), DLNPair(dentry),
++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
++ atomic_read(&dentry->d_count), dentry->d_flags);
++ do_pri_inode(bindex, dentry->d_inode);
++ return 0;
++}
++
++void au_dpri_dentry(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_dentry(-1, dentry);
++ if (err || !au_is_aufs(dentry->d_sb))
++ return;
++
++ dinfo = dtodi(dentry);
++ if (!dinfo)
++ return;
++ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
++ dinfo->di_bstart, dinfo->di_bend,
++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
++ if (dinfo->di_bstart < 0)
++ return;
++ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
++ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
++}
++
++static int do_pri_file(aufs_bindex_t bindex, struct file *file)
++{
++ char a[32];
++
++ if (!file || IS_ERR(file)) {
++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
++ return -1;
++ }
++ a[0] = 0;
++ if (bindex == -1 && ftofi(file))
++ snprintf(a, sizeof(a), ", mmapped %d", au_is_mmapped(file));
++ dpri("f%d: mode 0x%x, flags 0%o, cnt %d, pos %Lu%s\n",
++ bindex, file->f_mode, file->f_flags, file_count(file),
++ file->f_pos, a);
++ do_pri_dentry(bindex, file->f_dentry);
++ return 0;
++}
++
++void au_dpri_file(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_file(-1, file);
++ if (err || !file->f_dentry || !au_is_aufs(file->f_dentry->d_sb))
++ return;
++
++ finfo = ftofi(file);
++ if (!finfo)
++ return;
++ if (finfo->fi_bstart < 0)
++ return;
++ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
++ struct aufs_hfile *hf;
++ //dpri("bindex %d\n", bindex);
++ hf = finfo->fi_hfile + bindex;
++ do_pri_file(bindex, hf ? hf->hf_file : NULL);
++ }
++}
++
++static int do_pri_br(aufs_bindex_t bindex, struct aufs_branch *br)
++{
++ struct vfsmount *mnt;
++ struct super_block *sb;
++
++ if (!br || IS_ERR(br)
++ || !(mnt = br->br_mnt) || IS_ERR(mnt)
++ || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
++ return -1;
++ }
++
++ dpri("s%d: {perm 0x%x, cnt %d}, "
++ "%s, flags 0x%lx, cnt(BIAS) %d, active %d, xino %p %p\n",
++ bindex, br->br_perm, br_count(br),
++ au_sbtype(sb), sb->s_flags, sb->s_count - S_BIAS,
++ atomic_read(&sb->s_active), br->br_xino,
++ br->br_xino ? br->br_xino->f_dentry : NULL);
++ return 0;
++}
++
++void au_dpri_sb(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ aufs_bindex_t bindex;
++ int err;
++ struct vfsmount mnt = {.mnt_sb = sb};
++ struct aufs_branch fake = {
++ .br_perm = 0,
++ .br_mnt = &mnt,
++ .br_count = ATOMIC_INIT(0),
++ .br_xino = NULL
++ };
++
++ atomic_set(&fake.br_count, 0);
++ err = do_pri_br(-1, &fake);
++ dpri("dev 0x%x\n", sb->s_dev);
++ if (err || !au_is_aufs(sb))
++ return;
++
++ sbinfo = stosi(sb);
++ if (!sbinfo)
++ return;
++ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) {
++ //dpri("bindex %d\n", bindex);
++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void DbgSleep(int sec)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ Dbg("sleep %d sec\n", sec);
++ wait_event_timeout(wq, 0, sec * HZ);
++}
+diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h
+new file mode 100755
+index 0000000..53f5f6a
+--- /dev/null
++++ b/fs/aufs/debug.h
+@@ -0,0 +1,129 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: debug.h,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DEBUG_H__
++#define __AUFS_DEBUG_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++
++#ifdef CONFIG_AUFS_DEBUG
++#define DEBUG_ON(a) BUG_ON(a)
++extern atomic_t aufs_cond;
++#define au_debug_on() atomic_inc(&aufs_cond)
++#define au_debug_off() atomic_dec(&aufs_cond)
++#define au_is_debug() atomic_read(&aufs_cond)
++#else
++#define DEBUG_ON(a) /* */
++#define au_debug_on() /* */
++#define au_debug_off() /* */
++#define au_is_debug() 0
++#endif
++
++#define MtxMustLock(mtx) DEBUG_ON(!mutex_is_locked(mtx))
++
++/* ---------------------------------------------------------------------- */
++
++/* debug print */
++#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
++#include <linux/lktr.h>
++#ifdef CONFIG_AUFS_DEBUG
++#undef LktrCond
++#define LktrCond unlikely((lktr_cond && lktr_cond()) || au_is_debug())
++#endif
++#else
++#define LktrCond au_is_debug()
++#define LKTRDumpVma(pre, vma, suf) /* */
++#define LKTRDumpStack() /* */
++#define LKTRTrace(fmt, args...) do { \
++ if (LktrCond) \
++ Dbg(fmt, ##args); \
++} while (0)
++#define LKTRLabel(label) LKTRTrace("%s\n", #label)
++#endif /* CONFIG_LKTR */
++
++#define TraceErr(e) do { \
++ if (unlikely((e) < 0)) \
++ LKTRTrace("err %d\n", (int)(e)); \
++} while (0)
++#define TraceErrPtr(p) do { \
++ if (IS_ERR(p)) \
++ LKTRTrace("err %ld\n", PTR_ERR(p)); \
++} while (0)
++#define TraceEnter() LKTRLabel(enter)
++
++/* dirty macros for debug print, use with "%.*s" and caution */
++#define LNPair(qstr) (qstr)->len,(qstr)->name
++#define DLNPair(d) LNPair(&(d)->d_name)
++
++/* ---------------------------------------------------------------------- */
++
++#define Dpri(lvl, fmt, arg...) \
++ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
++ __func__, __LINE__, current->comm, current->pid, ##arg)
++#define Dbg(fmt, arg...) Dpri(KERN_DEBUG, fmt, ##arg)
++#define Warn(fmt, arg...) Dpri(KERN_WARNING, fmt, ##arg)
++#define Warn1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) Warn(fmt, ##arg); \
++ } while (0)
++#define Err(fmt, arg...) Dpri(KERN_ERR, fmt, ##arg)
++#define Err1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) Err(fmt, ##arg); \
++ } while (0)
++#define IOErr(fmt, arg...) Err("I/O Error, " fmt, ##arg)
++#define IOErr1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) IOErr(fmt, ##arg); \
++ } while (0)
++#define IOErrWhck(fmt, arg...) Err("I/O Error, try whck. " fmt, ##arg)
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DEBUG
++struct aufs_nhash;
++void au_dpri_whlist(struct aufs_nhash *whlist);
++struct aufs_vdir;
++void au_dpri_vdir(struct aufs_vdir *vdir);
++void au_dpri_inode(struct inode *inode);
++void au_dpri_dentry(struct dentry *dentry);
++void au_dpri_file(struct file *filp);
++void au_dpri_sb(struct super_block *sb);
++#define DbgWhlist(w) do{LKTRTrace(#w "\n"); au_dpri_whlist(w);}while(0)
++#define DbgVdir(v) do{LKTRTrace(#v "\n"); au_dpri_vdir(v);}while(0)
++#define DbgInode(i) do{LKTRTrace(#i "\n"); au_dpri_inode(i);}while(0)
++#define DbgDentry(d) do{LKTRTrace(#d "\n"); au_dpri_dentry(d);}while(0)
++#define DbgFile(f) do{LKTRTrace(#f "\n"); au_dpri_file(f);}while(0)
++#define DbgSb(sb) do{LKTRTrace(#sb "\n"); au_dpri_sb(sb);}while(0)
++void DbgSleep(int sec);
++#else
++#define DbgWhlist(w) /* */
++#define DbgVdir(v) /* */
++#define DbgInode(i) /* */
++#define DbgDentry(d) /* */
++#define DbgFile(f) /* */
++#define DbgSb(sb) /* */
++#define DbgSleep(sec) /* */
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DEBUG_H__ */
+diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
+new file mode 100755
+index 0000000..2acb89b
+--- /dev/null
++++ b/fs/aufs/dentry.c
+@@ -0,0 +1,946 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dentry.c,v 1.41 2007/05/14 03:38:38 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++#ifdef CONFIG_AUFS_LHASH_PATCH
++
++#ifdef CONFIG_AUFS_DLGT
++struct lookup_hash_args {
++ struct dentry **errp;
++ struct qstr *name;
++ struct dentry *base;
++ struct nameidata *nd;
++};
++
++static void call_lookup_hash(void *args)
++{
++ struct lookup_hash_args *a = args;
++ *a->errp = __lookup_hash(a->name, a->base, a->nd);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++static struct dentry *lkup_hash(const char *name, struct dentry *parent,
++ int len, struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++ char *p;
++ unsigned long hash;
++ struct qstr this;
++ unsigned int c;
++ struct nameidata tmp_nd;
++
++ dentry = ERR_PTR(-EACCES);
++ this.name = name;
++ this.len = len;
++ if (unlikely(!len))
++ goto out;
++
++ p = (void*)name;
++ hash = init_name_hash();
++ while (len--) {
++ c = *p++;
++ if (unlikely(c == '/' || c == '\0'))
++ goto out;
++ hash = partial_name_hash(c, hash);
++ }
++ this.hash = end_name_hash(hash);
++
++ memset(&tmp_nd, 0, sizeof(tmp_nd));
++ tmp_nd.dentry = dget(parent);
++ tmp_nd.mnt = mntget(lkup->nfsmnt);
++#ifndef CONFIG_AUFS_DLGT
++ dentry = __lookup_hash(&this, parent, &tmp_nd);
++#else
++ if (!lkup->dlgt)
++ dentry = __lookup_hash(&this, parent, &tmp_nd);
++ else {
++ struct lookup_hash_args args = {
++ .errp = &dentry,
++ .name = &this,
++ .base = parent,
++ .nd = &tmp_nd
++ };
++ au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
++ }
++#endif
++ path_release(&tmp_nd);
++
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++#elif defined(CONFIG_AUFS_DLGT)
++static struct dentry *lkup_hash(const char *name, struct dentry *parent,
++ int len, struct lkup_args *lkup)
++{
++ return ERR_PTR(-ENOSYS);
++}
++#endif
++
++#ifdef CONFIG_AUFS_DLGT
++struct lookup_one_len_args {
++ struct dentry **errp;
++ const char *name;
++ struct dentry *parent;
++ int len;
++};
++
++static void call_lookup_one_len(void *args)
++{
++ struct lookup_one_len_args *a = args;
++ *a->errp = lookup_one_len(a->name, a->parent, a->len);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
++/* cf. lookup_one_len() in linux/fs/namei.c */
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++
++ LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
++ DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);
++
++ if (!lkup->nfsmnt) {
++#ifndef CONFIG_AUFS_DLGT
++ dentry = lookup_one_len(name, parent, len);
++#else
++ if (!lkup->dlgt)
++ dentry = lookup_one_len(name, parent, len);
++ else {
++ struct lookup_one_len_args args = {
++ .errp = &dentry,
++ .name = name,
++ .parent = parent,
++ .len = len
++ };
++ au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1);
++ }
++#endif
++ } else
++ dentry = lkup_hash(name, parent, len, lkup);
++
++ TraceErrPtr(dentry);
++ return dentry;
++}
++#endif
++
++struct lkup_one_args {
++ struct dentry **errp;
++ const char *name;
++ struct dentry *parent;
++ int len;
++ struct lkup_args *lkup;
++};
++
++static void call_lkup_one(void *args)
++{
++ struct lkup_one_args *a = args;
++ *a->errp = lkup_one(a->name, a->parent, a->len, a->lkup);
++}
++
++/*
++ * returns positive/negative dentry, NULL or an error.
++ * NULL means whiteout-ed or not-found.
++ */
++static struct dentry *do_lookup(struct dentry *hidden_parent,
++ struct dentry *dentry, aufs_bindex_t bindex,
++ struct qstr *wh_name, int allow_neg,
++ mode_t type, int dlgt)
++{
++ struct dentry *hidden_dentry;
++ int wh_found, wh_able, opq;
++ struct inode *hidden_dir, *hidden_inode;
++ struct qstr *name;
++ struct super_block *sb;
++ struct lkup_args lkup = {.dlgt = dlgt};
++
++ LKTRTrace("%.*s/%.*s, b%d, allow_neg %d, type 0%o, dlgt %d\n",
++ DLNPair(hidden_parent), DLNPair(dentry), bindex, allow_neg,
++ type, dlgt);
++ DEBUG_ON(IS_ROOT(dentry));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ wh_found = 0;
++ sb = dentry->d_sb;
++ wh_able = sbr_is_whable(sb, bindex);
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ name = &dentry->d_name;
++ if (unlikely(wh_able)) {
++#if 0 //def CONFIG_AUFS_ROBR
++ if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
++ wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0,
++ &lkup);
++ else
++ wh_found = -EPERM;
++#else
++ wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0, &lkup);
++#endif
++ }
++ //if (LktrCond) wh_found = -1;
++ hidden_dentry = ERR_PTR(wh_found);
++ if (!wh_found)
++ goto real_lookup;
++ if (unlikely(wh_found < 0))
++ goto out;
++
++ /* We found a whiteout */
++ //set_dbend(dentry, bindex);
++ set_dbwh(dentry, bindex);
++ if (!allow_neg)
++ return NULL; /* success */
++
++ real_lookup:
++ // do not superio.
++ hidden_dentry = lkup_one(name->name, hidden_parent, name->len, &lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ if (IS_ERR(hidden_dentry))
++ goto out;
++ DEBUG_ON(d_unhashed(hidden_dentry));
++ hidden_inode = hidden_dentry->d_inode;
++ if (!hidden_inode) {
++ if (!allow_neg)
++ goto out_neg;
++ } else if (wh_found
++ || (type && type != (hidden_inode->i_mode & S_IFMT)))
++ goto out_neg;
++
++ if (dbend(dentry) <= bindex)
++ set_dbend(dentry, bindex);
++ if (dbstart(dentry) == -1 || bindex < dbstart(dentry))
++ set_dbstart(dentry, bindex);
++ set_h_dptr(dentry, bindex, hidden_dentry);
++
++ if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode) || !wh_able)
++ return hidden_dentry; /* success */
++
++ hi_lock_child(hidden_inode);
++ opq = is_diropq(hidden_dentry, &lkup);
++ //if (LktrCond) opq = -1;
++ i_unlock(hidden_inode);
++ if (opq > 0)
++ set_dbdiropq(dentry, bindex);
++ else if (unlikely(opq < 0)) {
++ set_h_dptr(dentry, bindex, NULL);
++ hidden_dentry = ERR_PTR(opq);
++ }
++ goto out;
++
++ out_neg:
++ dput(hidden_dentry);
++ hidden_dentry = NULL;
++ out:
++ TraceErrPtr(hidden_dentry);
++ return hidden_dentry;
++}
++
++/*
++ * returns the number of hidden positive dentries,
++ * otherwise an error.
++ */
++int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
++{
++ int npositive, err, allow_neg, dlgt;
++ struct dentry *parent;
++ aufs_bindex_t bindex, btail;
++ const struct qstr *name = &dentry->d_name;
++ struct qstr whname;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, b%d, type 0%o\n", LNPair(name), bstart, type);
++ DEBUG_ON(bstart < 0 || IS_ROOT(dentry));
++ parent = dget_parent(dentry);
++
++#if 1 //ndef CONFIG_AUFS_ROBR
++ err = -EPERM;
++ if (unlikely(!strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ goto out;
++#endif
++
++ err = au_alloc_whname(name->name, name->len, &whname);
++ //if (LktrCond) {au_free_whname(&whname); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ sb = dentry->d_sb;
++ dlgt = need_dlgt(sb);
++ allow_neg = !type;
++ npositive = 0;
++ btail = dbtaildir(parent);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ struct dentry *hidden_parent, *hidden_dentry;
++ struct inode *hidden_inode;
++ struct inode *hidden_dir;
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry) {
++ if (hidden_dentry->d_inode)
++ npositive++;
++ if (type != S_IFDIR)
++ break;
++ continue;
++ }
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ if (!hidden_parent)
++ continue;
++ hidden_dir = hidden_parent->d_inode;
++ if (!hidden_dir || !S_ISDIR(hidden_dir->i_mode))
++ continue;
++
++ hi_lock_parent(hidden_dir);
++ hidden_dentry = do_lookup(hidden_parent, dentry, bindex,
++ &whname, allow_neg, type, dlgt);
++ // do not dput for testing
++ //if (LktrCond) {hidden_dentry = ERR_PTR(-1);}
++ i_unlock(hidden_dir);
++ err = PTR_ERR(hidden_dentry);
++ if (IS_ERR(hidden_dentry))
++ goto out_wh;
++ allow_neg = 0;
++
++ if (dbwh(dentry) != -1)
++ break;
++ if (!hidden_dentry)
++ continue;
++ hidden_inode = hidden_dentry->d_inode;
++ if (!hidden_inode)
++ continue;
++ npositive++;
++ if (!type)
++ type = hidden_inode->i_mode & S_IFMT;
++ if (type != S_IFDIR)
++ break;
++ else if (dbdiropq(dentry) != -1)
++ break;
++ }
++
++ if (npositive) {
++ LKTRLabel(positive);
++ au_update_dbstart(dentry);
++ }
++ err = npositive;
++
++ out_wh:
++ au_free_whname(&whname);
++ out:
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(parent), len, name);
++ IMustLock(parent->d_inode);
++
++ if (!au_test_perm(parent->d_inode, MAY_EXEC, lkup->dlgt))
++ dentry = lkup_one(name, parent, len, lkup);
++ else {
++ // ugly
++ int dlgt = lkup->dlgt;
++ struct lkup_one_args args = {
++ .errp = &dentry,
++ .name = name,
++ .parent = parent,
++ .len = len,
++ .lkup = lkup
++ };
++
++ lkup->dlgt = 0;
++ au_wkq_wait(call_lkup_one, &args, /*dlgt*/0);
++ lkup->dlgt = dlgt;
++ }
++
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/*
++ * lookup @dentry on @bindex which should be negative.
++ */
++int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct dentry *parent, *hidden_parent, *hidden_dentry;
++ struct inode *hidden_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++ parent = dget_parent(dentry);
++ DEBUG_ON(!parent || !parent->d_inode
++ || !S_ISDIR(parent->d_inode->i_mode));
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ DEBUG_ON(!hidden_parent);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bindex);
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ hidden_dentry = sio_lkup_one(dentry->d_name.name, hidden_parent,
++ dentry->d_name.len, &lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(hidden_dentry);
++ if (IS_ERR(hidden_dentry))
++ goto out;
++ if (unlikely(hidden_dentry->d_inode)) {
++ err = -EIO;
++ IOErr("b%d %.*s should be negative.%s\n",
++ bindex, DLNPair(hidden_dentry),
++ au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY) ? "" :
++ " Try udba=inotify.");
++ dput(hidden_dentry);
++ goto out;
++ }
++
++ if (bindex < dbstart(dentry))
++ set_dbstart(dentry, bindex);
++ if (dbend(dentry) < bindex)
++ set_dbend(dentry, bindex);
++ set_h_dptr(dentry, bindex, hidden_dentry);
++ err = 0;
++
++ out:
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns the number of found hidden positive dentries,
++ * otherwise an error.
++ */
++int au_refresh_hdentry(struct dentry *dentry, mode_t type)
++{
++ int npositive, pgen, new_sz, sgen, dgen;
++ struct aufs_dinfo *dinfo;
++ struct super_block *sb;
++ struct dentry *parent;
++ aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
++ struct aufs_hdentry *p;
++ //struct nameidata nd;
++
++ LKTRTrace("%.*s, type 0%o\n", DLNPair(dentry), type);
++ DiMustWriteLock(dentry);
++ sb = dentry->d_sb;
++ DEBUG_ON(IS_ROOT(dentry));
++ parent = dget_parent(dentry);
++ pgen = au_digen(parent);
++ sgen = au_sigen(sb);
++ dgen = au_digen(dentry);
++ DEBUG_ON(pgen != sgen);
++
++ npositive = -ENOMEM;
++ new_sz = sizeof(*dinfo->di_hdentry) * (sbend(sb) + 1);
++ dinfo = dtodi(dentry);
++ p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++ dinfo->di_hdentry = p;
++
++ bend = dinfo->di_bend;
++ bwh = dinfo->di_bwh;
++ bdiropq = dinfo->di_bdiropq;
++ p += dinfo->di_bstart;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
++ struct dentry *hd, *hdp;
++ struct aufs_hdentry tmp, *q;
++ aufs_bindex_t new_bindex;
++
++ hd = p->hd_dentry;
++ if (!hd)
++ continue;
++ hdp = dget_parent(hd);
++ if (hdp == au_h_dptr_i(parent, bindex)) {
++ dput(hdp);
++ continue;
++ }
++
++ new_bindex = au_find_dbindex(parent, hdp);
++ dput(hdp);
++ DEBUG_ON(new_bindex == bindex);
++ if (dinfo->di_bwh == bindex)
++ bwh = new_bindex;
++ if (dinfo->di_bdiropq == bindex)
++ bdiropq = new_bindex;
++ if (new_bindex < 0) { // test here
++ hdput(p);
++ p->hd_dentry = NULL;
++ continue;
++ }
++ /* swap two hidden dentries, and loop again */
++ q = dinfo->di_hdentry + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hd_dentry) {
++ bindex--;
++ p--;
++ }
++ }
++
++ // test here
++ dinfo->di_bwh = -1;
++ if (unlikely(bwh != -1 && bwh <= sbend(sb) && sbr_is_whable(sb, bwh)))
++ dinfo->di_bwh = bwh;
++ dinfo->di_bdiropq = -1;
++ if (unlikely(bdiropq != -1 && bdiropq <= sbend(sb)
++ && sbr_is_whable(sb, bdiropq)))
++ dinfo->di_bdiropq = bdiropq;
++ parent_bend = dbend(parent);
++ p = dinfo->di_hdentry;
++ for (bindex = 0; bindex <= parent_bend; bindex++, p++)
++ if (p->hd_dentry) {
++ dinfo->di_bstart = bindex;
++ break;
++ }
++ p = dinfo->di_hdentry + parent_bend;
++ //for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
++ for (bindex = parent_bend; bindex >= 0; bindex--, p--)
++ if (p->hd_dentry) {
++ dinfo->di_bend = bindex;
++ break;
++ }
++
++ npositive = 0;
++ parent_bstart = dbstart(parent);
++ if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
++ goto out_dgen; /* success */
++
++#if 0
++ nd.last_type = LAST_ROOT;
++ nd.flags = LOOKUP_FOLLOW;
++ nd.depth = 0;
++ nd.mnt = mntget(??);
++ nd.dentry = dget(parent);
++#endif
++ npositive = lkup_dentry(dentry, parent_bstart, type);
++ //if (LktrCond) npositive = -1;
++ if (npositive < 0)
++ goto out;
++
++ out_dgen:
++ au_update_digen(dentry);
++ out:
++ dput(parent);
++ TraceErr(npositive);
++ return npositive;
++}
++
++static int h_d_revalidate(struct dentry *dentry, struct nameidata *nd,
++ int do_udba)
++{
++ int err, plus, locked, unhashed, is_root, h_plus, is_nfs;
++ struct nameidata fake_nd, *p;
++ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
++ struct super_block *sb;
++ struct inode *inode, *first, *h_inode, *h_cached_inode;
++ umode_t mode, h_mode;
++ struct dentry *h_dentry;
++ int (*reval)(struct dentry *, struct nameidata *);
++ struct qstr *name;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(inode && au_digen(dentry) != au_iigen(inode));
++ //DbgDentry(dentry);
++ //DbgInode(inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ plus = 0;
++ mode = 0;
++ first = NULL;
++ ibs = ibe = -1;
++ unhashed = d_unhashed(dentry);
++ is_root = IS_ROOT(dentry);
++ name = &dentry->d_name;
++
++ /*
++ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
++ * But inotify doesn't fire some necessary events,
++ * IN_ATTRIB for atime/nlink/pageio
++ * IN_DELETE for NFS dentry
++ * Let's do REVAL test too.
++ */
++ if (do_udba && inode) {
++ mode = (inode->i_mode & S_IFMT);
++ plus = (inode->i_nlink > 0);
++ first = au_h_iptr(inode);
++ ibs = ibstart(inode);
++ ibe = ibend(inode);
++ }
++
++ btail = bstart = dbstart(dentry);
++ if (inode && S_ISDIR(inode->i_mode))
++ btail = dbtaildir(dentry);
++ locked = 0;
++ if (nd) {
++ fake_nd = *nd;
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (dentry != nd->dentry) {
++ di_read_lock_parent(nd->dentry, 0);
++ locked = 1;
++ }
++#endif
++ }
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr_i(dentry, bindex);
++ if (unlikely(!h_dentry))
++ continue;
++ if (unlikely(do_udba
++ && !is_root
++ && (unhashed != d_unhashed(h_dentry)
++#if 1
++ || name->len != h_dentry->d_name.len
++ || memcmp(name->name, h_dentry->d_name.name,
++ name->len)
++#endif
++ ))) {
++ LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
++ unhashed, d_unhashed(h_dentry),
++ DLNPair(dentry), DLNPair(h_dentry));
++ goto err;
++ }
++
++ reval = NULL;
++ if (h_dentry->d_op)
++ reval = h_dentry->d_op->d_revalidate;
++ if (unlikely(reval)) {
++ //LKTRLabel(hidden reval);
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ DEBUG_ON(IS_ERR(p));
++ err = !reval(h_dentry, p);
++ fake_dm_release(p);
++ if (unlikely(err)) {
++ //Dbg("here\n");
++ goto err;
++ }
++ }
++
++ if (unlikely(!do_udba))
++ continue;
++
++ /* UDBA tests */
++ h_inode = h_dentry->d_inode;
++ if (unlikely(!!inode != !!h_inode)) {
++ //Dbg("here\n");
++ goto err;
++ }
++
++ h_plus = plus;
++ h_mode = mode;
++ h_cached_inode = h_inode;
++ is_nfs = 0;
++ if (h_inode) {
++ h_mode = (h_inode->i_mode & S_IFMT);
++ h_plus = (h_inode->i_nlink > 0);
++ }
++ if (inode && ibs <= bindex && bindex <= ibe) {
++ h_cached_inode = au_h_iptr_i(inode, bindex);
++ //is_nfs = au_is_nfs(h_cached_inode->i_sb);
++ }
++
++ LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
++ plus, mode, h_cached_inode,
++ h_plus, h_mode, h_inode);
++ if (unlikely(plus != h_plus || mode != h_mode
++ || (h_cached_inode != h_inode /* && !is_nfs */))) {
++ //Dbg("here\n");
++ goto err;
++ }
++ continue;
++
++ err:
++ err = -EINVAL;
++ break;
++ }
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (unlikely(locked))
++ di_read_unlock(nd->dentry, 0);
++#endif
++
++#if 0
++ // some filesystem uses CURRENT_TIME_SEC instead of CURRENT_TIME.
++ // NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
++#if 0
++ && (!timespec_equal(&inode->i_ctime, &first->i_ctime)
++ || !timespec_equal(&inode->i_atime, &first->i_atime))
++#endif
++ if (unlikely(!err && udba && first))
++ au_cpup_attr_all(inode);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++static int simple_reval_dpath(struct dentry *dentry, int sgen)
++{
++ int err;
++ mode_t type;
++ struct dentry *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
++ SiMustAnyLock(dentry->d_sb);
++ DiMustWriteLock(dentry);
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode);
++
++ if (au_digen(dentry) == sgen)
++ return 0;
++
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ DEBUG_ON(au_digen(parent) != sgen);
++#ifdef CONFIG_AUFS_DEBUG
++ {
++ struct dentry *d = parent;
++ while (!IS_ROOT(d)) {
++ DEBUG_ON(au_digen(d) != sgen);
++ d = d->d_parent;
++ }
++ }
++#endif
++ type = (inode->i_mode & S_IFMT);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, type);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, dentry);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++int au_reval_dpath(struct dentry *dentry, int sgen)
++{
++ int err;
++ struct dentry *d, *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
++ DEBUG_ON(!dentry->d_inode);
++ DiMustWriteLock(dentry);
++
++ if (!stosi(dentry->d_sb)->si_failed_refresh_dirs)
++ return simple_reval_dpath(dentry, sgen);
++
++ /* slow loop, keep it simple and stupid */
++ /* cf: cpup_dirs() */
++ err = 0;
++ while (au_digen(dentry) != sgen) {
++ d = dentry;
++ while (1) {
++ parent = d->d_parent; // dget_parent()
++ if (au_digen(parent) == sgen)
++ break;
++ d = parent;
++ }
++
++ inode = d->d_inode;
++ if (d != dentry) {
++ //i_lock(inode);
++ di_write_lock_child(d);
++ }
++
++ /* someone might update our dentry while we were sleeping */
++ if (au_digen(d) != sgen) {
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
++ //err = -1;
++ if (err >= 0)
++ err = au_refresh_hinode(inode, d);
++ //err = -1;
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++
++ if (d != dentry) {
++ di_write_unlock(d);
++ //i_unlock(inode);
++ }
++ if (unlikely(err))
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
++ * nfsd passes NULL as nameidata.
++ */
++static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
++{
++ int valid, sgen, err, do_udba;
++ struct super_block *sb;
++ struct inode *inode;
++
++ LKTRTrace("dentry %.*s\n", DLNPair(dentry));
++ if (nd && nd->dentry)
++ LKTRTrace("nd %.*s\n", DLNPair(nd->dentry));
++ //dir case: DEBUG_ON(dentry->d_parent != nd->dentry);
++ //remove failure case: DEBUG_ON(!IS_ROOT(dentry) && d_unhashed(dentry));
++ DEBUG_ON(!dentry->d_fsdata);
++ //DbgDentry(dentry);
++
++ err = -EINVAL;
++ inode = dentry->d_inode;
++ //DbgInode(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ sgen = au_sigen(sb);
++ if (au_digen(dentry) == sgen)
++ di_read_lock_child(dentry, !AUFS_I_RLOCK);
++ else {
++ DEBUG_ON(IS_ROOT(dentry));
++#ifdef ForceInotify
++ Dbg("UDBA or digen, %.*s\n", DLNPair(dentry));
++#endif
++ //i_lock(inode);
++ di_write_lock_child(dentry);
++ if (inode)
++ err = au_reval_dpath(dentry, sgen);
++ //err = -1;
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ //i_unlock(inode);
++ if (unlikely(err))
++ goto out;
++ ii_read_unlock(inode);
++ DEBUG_ON(au_iigen(inode) != sgen);
++ }
++
++ if (inode) {
++ if (au_iigen(inode) == sgen)
++ ii_read_lock_child(inode);
++ else {
++ DEBUG_ON(IS_ROOT(dentry));
++#ifdef ForceInotify
++ Dbg("UDBA or survived, %.*s\n", DLNPair(dentry));
++#endif
++ ii_write_lock_child(inode);
++ err = au_refresh_hinode(inode, dentry);
++ ii_downgrade_lock(inode);
++ if (unlikely(err))
++ goto out;
++ DEBUG_ON(au_iigen(inode) != sgen);
++ }
++ }
++
++#if 0 // fix it
++ /* parent dir i_nlink is not updated in the case of setattr */
++ if (S_ISDIR(inode->i_mode)) {
++ i_lock(inode);
++ ii_write_lock(inode);
++ au_cpup_attr_nlink(inode);
++ ii_write_unlock(inode);
++ i_unlock(inode);
++ }
++#endif
++
++ err = -EINVAL;
++ do_udba = !au_flag_test(sb, AuFlag_UDBA_NONE);
++ if (do_udba && inode && ibstart(inode) >= 0
++ && au_test_higen(inode, au_h_iptr(inode)))
++ goto out;
++ err = h_d_revalidate(dentry, nd, do_udba);
++ //err = -1;
++
++ out:
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ TraceErr(err);
++ valid = !err;
++ //au_debug_on();
++ if (!valid)
++ LKTRTrace("%.*s invalid\n", DLNPair(dentry));
++ //au_debug_off();
++ return valid;
++}
++
++static void aufs_d_release(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!d_unhashed(dentry));
++
++ dinfo = dentry->d_fsdata;
++ if (unlikely(!dinfo))
++ return;
++
++ /* dentry may not be revalidated */
++ bindex = dinfo->di_bstart;
++ if (bindex >= 0) {
++ struct aufs_hdentry *p;
++ bend = dinfo->di_bend;
++ DEBUG_ON(bend < bindex);
++ p = dinfo->di_hdentry + bindex;
++ while (bindex++ <= bend) {
++ if (p->hd_dentry)
++ hdput(p);
++ p++;
++ }
++ }
++ kfree(dinfo->di_hdentry);
++ cache_free_dinfo(dinfo);
++}
++
++#if 0
++/* it may be called at remount time, too */
++static void aufs_d_iput(struct dentry *dentry, struct inode *inode)
++{
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, i%lu\n", DLNPair(dentry), inode->i_ino);
++
++ sb = dentry->d_sb;
++#if 0
++ si_read_lock(sb);
++ if (unlikely(au_flag_test(sb, AuFlag_PLINK)
++ && au_is_plinked(sb, inode))) {
++ ii_write_lock(inode);
++ au_update_brange(inode, 1);
++ ii_write_unlock(inode);
++ }
++ si_read_unlock(sb);
++#endif
++ iput(inode);
++}
++#endif
++
++struct dentry_operations aufs_dop = {
++ .d_revalidate = aufs_d_revalidate,
++ .d_release = aufs_d_release
++ //.d_iput = aufs_d_iput
++};
+diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
+new file mode 100755
+index 0000000..78049e3
+--- /dev/null
++++ b/fs/aufs/dentry.h
+@@ -0,0 +1,183 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dentry.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DENTRY_H__
++#define __AUFS_DENTRY_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++
++struct aufs_hdentry {
++ struct dentry *hd_dentry;
++};
++
++struct aufs_dinfo {
++ atomic_t di_generation;
++
++ struct aufs_rwsem di_rwsem;
++ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
++ struct aufs_hdentry *di_hdentry;
++};
++
++struct lkup_args {
++ struct vfsmount *nfsmnt;
++ int dlgt;
++ //struct super_block *sb;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry.c */
++#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup);
++#else
++static inline
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ return lookup_one_len(name, parent, len);
++}
++#endif
++
++extern struct dentry_operations aufs_dop;
++struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup);
++int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type);
++int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
++int au_refresh_hdentry(struct dentry *dentry, mode_t type);
++int au_reval_dpath(struct dentry *dentry, int sgen);
++
++/* dinfo.c */
++int au_alloc_dinfo(struct dentry *dentry);
++struct aufs_dinfo *dtodi(struct dentry *dentry);
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
++void di_read_unlock(struct dentry *d, int flags);
++void di_downgrade_lock(struct dentry *d, int flags);
++void di_write_lock(struct dentry *d, unsigned int lsc);
++void di_write_unlock(struct dentry *d);
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++aufs_bindex_t dbstart(struct dentry *dentry);
++aufs_bindex_t dbend(struct dentry *dentry);
++aufs_bindex_t dbwh(struct dentry *dentry);
++aufs_bindex_t dbdiropq(struct dentry *dentry);
++struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex);
++struct dentry *au_h_dptr(struct dentry *dentry);
++
++aufs_bindex_t dbtail(struct dentry *dentry);
++aufs_bindex_t dbtaildir(struct dentry *dentry);
++aufs_bindex_t dbtail_generic(struct dentry *dentry);
++
++void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbend(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
++void hdput(struct aufs_hdentry *hdentry);
++void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++
++void au_update_digen(struct dentry *dentry);
++void au_update_dbstart(struct dentry *dentry);
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_digen(struct dentry *d)
++{
++ return atomic_read(&dtodi(d)->di_generation);
++}
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_digen_dec(struct dentry *d)
++{
++ atomic_dec(&dtodi(d)->di_generation);
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for dinfo */
++enum {
++ AuLsc_DI_CHILD, /* child first */
++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_DI_CHILD3, /* copyup dirs */
++ AuLsc_DI_PARENT,
++ AuLsc_DI_PARENT2,
++ AuLsc_DI_PARENT3
++};
++
++/*
++ * di_read_lock_child, di_write_lock_child,
++ * di_read_lock_child2, di_write_lock_child2,
++ * di_read_lock_child3, di_write_lock_child3,
++ * di_read_lock_parent, di_write_lock_parent,
++ * di_read_lock_parent2, di_write_lock_parent2,
++ * di_read_lock_parent3, di_write_lock_parent3,
++ */
++#define ReadLockFunc(name, lsc) \
++static inline void di_read_lock_##name(struct dentry *d, int flags) \
++{di_read_lock(d, flags, AuLsc_DI_##lsc);}
++
++#define WriteLockFunc(name, lsc) \
++static inline void di_write_lock_##name(struct dentry *d) \
++{di_write_lock(d, AuLsc_DI_##lsc);}
++
++#define RWLockFuncs(name, lsc) \
++ ReadLockFunc(name, lsc); \
++ WriteLockFunc(name, lsc)
++
++RWLockFuncs(child, CHILD);
++RWLockFuncs(child2, CHILD2);
++RWLockFuncs(child3, CHILD3);
++RWLockFuncs(parent, PARENT);
++RWLockFuncs(parent2, PARENT2);
++RWLockFuncs(parent3, PARENT3);
++
++#undef ReadLockFunc
++#undef WriteLockFunc
++#undef RWLockFunc
++
++/* to debug easier, do not make them inlined functions */
++#define DiMustReadLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustReadLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustWriteLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustWriteLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustAnyLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustAnyLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustNoWaiters(d) RwMustNoWaiters(&dtodi(d)->di_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DENTRY_H__ */
+diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
+new file mode 100755
+index 0000000..6082149
+--- /dev/null
++++ b/fs/aufs/dinfo.c
+@@ -0,0 +1,419 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dinfo.c,v 1.23 2007/05/07 03:43:36 sfjro Exp $ */
++
++#include "aufs.h"
++
++int au_alloc_dinfo(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ struct super_block *sb;
++ int nbr;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(dentry->d_fsdata);
++
++ dinfo = cache_alloc_dinfo();
++ //if (LktrCond) {cache_free_dinfo(dinfo); dinfo = NULL;}
++ if (dinfo) {
++ sb = dentry->d_sb;
++ nbr = sbend(sb) + 1;
++ if (unlikely(!nbr))
++ nbr++;
++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
++ GFP_KERNEL);
++ //if (LktrCond)
++ //{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
++ if (dinfo->di_hdentry) {
++ rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
++ dinfo->di_bstart = dinfo->di_bend = -1;
++ dinfo->di_bwh = dinfo->di_bdiropq = -1;
++ atomic_set(&dinfo->di_generation, au_sigen(sb));
++
++ dentry->d_fsdata = dinfo;
++ dentry->d_op = &aufs_dop;
++ return 0; /* success */
++ }
++ cache_free_dinfo(dinfo);
++ }
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
++
++struct aufs_dinfo *dtodi(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo = dentry->d_fsdata;
++ DEBUG_ON(!dinfo
++ || !dinfo->di_hdentry
++ /* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
++ || dinfo->di_bend < dinfo->di_bstart
++ /* dbwh can be outside of this range */
++ || (0 <= dinfo->di_bdiropq
++ && (dinfo->di_bdiropq < dinfo->di_bstart
++ /* || dinfo->di_bend < dinfo->di_bdiropq */))
++ );
++ return dinfo;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_write_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_write_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_write_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_write_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_write_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_write_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_read_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_read_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_read_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_read_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_read_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_read_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
++{
++ SiMustAnyLock(d->d_sb);
++ // todo: always nested?
++ rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
++ if (d->d_inode) {
++ if (flags & AUFS_I_WLOCK)
++ do_ii_write_lock(d->d_inode, lsc);
++ else if (flags & AUFS_I_RLOCK)
++ do_ii_read_lock(d->d_inode, lsc);
++ }
++}
++
++void di_read_unlock(struct dentry *d, int flags)
++{
++ SiMustAnyLock(d->d_sb);
++ if (d->d_inode) {
++ if (flags & AUFS_I_WLOCK)
++ ii_write_unlock(d->d_inode);
++ else if (flags & AUFS_I_RLOCK)
++ ii_read_unlock(d->d_inode);
++ }
++ rw_read_unlock(&dtodi(d)->di_rwsem);
++}
++
++void di_downgrade_lock(struct dentry *d, int flags)
++{
++ SiMustAnyLock(d->d_sb);
++ rw_dgrade_lock(&dtodi(d)->di_rwsem);
++ if (d->d_inode && (flags & AUFS_I_RLOCK))
++ ii_downgrade_lock(d->d_inode);
++}
++
++void di_write_lock(struct dentry *d, unsigned int lsc)
++{
++ SiMustAnyLock(d->d_sb);
++ // todo: always nested?
++ rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
++ if (d->d_inode)
++ do_ii_write_lock(d->d_inode, lsc);
++}
++
++void di_write_unlock(struct dentry *d)
++{
++ SiMustAnyLock(d->d_sb);
++ if (d->d_inode)
++ ii_write_unlock(d->d_inode);
++ rw_write_unlock(&dtodi(d)->di_rwsem);
++}
++
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ struct dentry *d;
++
++ TraceEnter();
++ DEBUG_ON(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir)
++ for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
++ if (d->d_parent == d2) {
++ di_write_lock_child(d1);
++ di_write_lock_child2(d2);
++ return;
++ }
++
++ di_write_lock_child(d2);
++ di_write_lock_child2(d1);
++}
++
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ struct dentry *d;
++
++ TraceEnter();
++ DEBUG_ON(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir)
++ for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
++ if (d->d_parent == d2) {
++ di_write_lock_parent(d1);
++ di_write_lock_parent2(d2);
++ return;
++ }
++
++ di_write_lock_parent(d2);
++ di_write_lock_parent2(d1);
++}
++
++void di_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock(d1);
++ if (d1->d_inode == d2->d_inode)
++ rw_write_unlock(&dtodi(d2)->di_rwsem);
++ else
++ di_write_unlock(d2);
++}
++
++/* ---------------------------------------------------------------------- */
++
++aufs_bindex_t dbstart(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bstart;
++}
++
++aufs_bindex_t dbend(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bend;
++}
++
++aufs_bindex_t dbwh(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bwh;
++}
++
++aufs_bindex_t dbdiropq(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ DEBUG_ON(dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode));
++ return dtodi(dentry)->di_bdiropq;
++}
++
++struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ struct dentry *d;
++
++ DiMustAnyLock(dentry);
++ if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
++ return NULL;
++ DEBUG_ON(bindex < 0
++ /* || bindex > sbend(dentry->d_sb) */);
++ d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
++ DEBUG_ON(d && (atomic_read(&d->d_count) <= 0));
++ return d;
++}
++
++struct dentry *au_h_dptr(struct dentry *dentry)
++{
++ return au_h_dptr_i(dentry, dbstart(dentry));
++}
++
++aufs_bindex_t dbtail(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bwh;
++
++ bend = dbend(dentry);
++ if (0 <= bend) {
++ bwh = dbwh(dentry);
++ //DEBUG_ON(bend < bwh);
++ if (!bwh)
++ return bwh;
++ if (0 < bwh && bwh < bend)
++ return bwh - 1;
++ }
++ return bend;
++}
++
++aufs_bindex_t dbtaildir(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bopq;
++
++ DEBUG_ON(dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode));
++
++ bend = dbtail(dentry);
++ if (0 <= bend) {
++ bopq = dbdiropq(dentry);
++ DEBUG_ON(bend < bopq);
++ if (0 <= bopq && bopq < bend)
++ bend = bopq;
++ }
++ return bend;
++}
++
++aufs_bindex_t dbtail_generic(struct dentry *dentry)
++{
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (inode && S_ISDIR(inode->i_mode))
++ return dbtaildir(dentry);
++ else
++ return dbtail(dentry);
++}
++
++/* ---------------------------------------------------------------------- */
++
++// hard/soft set
++void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ /* */
++ dtodi(dentry)->di_bstart = bindex;
++}
++
++void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex
++ || bindex < dbstart(dentry));
++ dtodi(dentry)->di_bend = bindex;
++}
++
++void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ /* dbwh can be outside of bstart - bend range */
++ dtodi(dentry)->di_bwh = bindex;
++}
++
++void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ DEBUG_ON((bindex != -1
++ && (bindex < dbstart(dentry) || dbend(dentry) < bindex))
++ || (dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode)));
++ dtodi(dentry)->di_bdiropq = bindex;
++}
++
++void hdput(struct aufs_hdentry *hd)
++{
++ dput(hd->hd_dentry);
++}
++
++void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
++ DiMustWriteLock(dentry);
++ DEBUG_ON(bindex < dtodi(dentry)->di_bstart
++ || bindex > dtodi(dentry)->di_bend
++ || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
++ || (h_dentry && hd->hd_dentry)
++ );
++ if (hd->hd_dentry)
++ hdput(hd);
++ hd->hd_dentry = h_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_update_digen(struct dentry *dentry)
++{
++ //DiMustWriteLock(dentry);
++ DEBUG_ON(!dentry->d_sb);
++ atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
++}
++
++void au_update_dbstart(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
++ struct dentry *hidden_dentry;
++
++ DiMustWriteLock(dentry);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ if (hidden_dentry->d_inode) {
++ set_dbstart(dentry, bindex);
++ return;
++ }
++ set_h_dptr(dentry, bindex, NULL);
++ }
++ //set_dbstart(dentry, -1);
++ //set_dbend(dentry, -1);
++}
++
++int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++)
++ if (au_h_dptr_i(dentry, bindex) == hidden_dentry)
++ return bindex;
++ return -1;
++}
+diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c
+new file mode 100755
+index 0000000..9afb1a9
+--- /dev/null
++++ b/fs/aufs/dir.c
+@@ -0,0 +1,564 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dir.c,v 1.36 2007/05/14 03:38:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static int reopen_dir(struct file *file)
++{
++ int err;
++ struct dentry *dentry, *hidden_dentry;
++ aufs_bindex_t bindex, btail, bstart;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++
++ /* open all hidden dirs */
++ bstart = dbstart(dentry);
++#if 1
++ for (bindex = fbstart(file); bindex < bstart; bindex++)
++ set_h_fptr(file, bindex, NULL);
++#endif
++ set_fbstart(file, bstart);
++ btail = dbtaildir(dentry);
++#if 1
++ for (bindex = fbend(file); btail < bindex; bindex--)
++ set_h_fptr(file, bindex, NULL);
++#endif
++ set_fbend(file, btail);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (hidden_file) {
++ DEBUG_ON(hidden_file->f_dentry != hidden_dentry);
++ continue;
++ }
++
++ hidden_file = hidden_open(dentry, bindex, file->f_flags);
++ // unavailable
++ //if (LktrCond) {fput(hidden_file);
++ //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out; // close all?
++ //cpup_file_flags(hidden_file, file);
++ set_h_fptr(file, bindex, hidden_file);
++ }
++ err = 0;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int do_open_dir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex, btail;
++ struct dentry *dentry, *hidden_dentry;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, 0x%x\n", DLNPair(dentry), flags);
++ DEBUG_ON(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
++
++ err = 0;
++ set_fvdir_cache(file, NULL);
++ file->f_version = dentry->d_inode->i_version;
++ bindex = dbstart(dentry);
++ set_fbstart(file, bindex);
++ btail = dbtaildir(dentry);
++ set_fbend(file, btail);
++ for (; !err && bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++
++ hidden_file = hidden_open(dentry, bindex, flags);
++ //if (LktrCond) {fput(hidden_file);
++ //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
++ if (!IS_ERR(hidden_file)) {
++ set_h_fptr(file, bindex, hidden_file);
++ continue;
++ }
++ err = PTR_ERR(hidden_file);
++ }
++ if (!err)
++ return 0; /* success */
++
++ /* close all */
++ for (bindex = fbstart(file); !err && bindex <= btail; bindex++)
++ set_h_fptr(file, bindex, NULL);
++ set_fbstart(file, -1);
++ set_fbend(file, -1);
++ return err;
++}
++
++static int aufs_open_dir(struct inode *inode, struct file *file)
++{
++ return au_do_open(inode, file, do_open_dir);
++}
++
++static int aufs_release_dir(struct inode *inode, struct file *file)
++{
++ struct aufs_vdir *vdir_cache;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
++
++ sb = file->f_dentry->d_sb;
++ si_read_lock(sb);
++ fi_write_lock(file);
++ vdir_cache = fvdir_cache(file);
++ if (vdir_cache)
++ free_vdir(vdir_cache);
++ fi_write_unlock(file);
++ au_fin_finfo(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++static int fsync_dir(struct dentry *dentry, int datasync)
++{
++ int err;
++ struct inode *inode;
++ struct super_block *sb;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ DiMustAnyLock(dentry);
++ sb = dentry->d_sb;
++ SiMustAnyLock(sb);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ IiMustAnyLock(inode);
++
++ err = 0;
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); !err && bindex <= bend; bindex++) {
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct file_operations *fop;
++
++ if (test_ro(sb, bindex, inode))
++ continue;
++ h_dentry = au_h_dptr_i(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ h_inode = h_dentry->d_inode;
++ if (!h_inode)
++ continue;
++
++ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
++ //hdir_lock(h_inode, inode, bindex);
++ i_lock(h_inode);
++ fop = (void*)h_inode->i_fop;
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ if (!err && fop && fop->fsync)
++ err = fop->fsync(NULL, h_dentry, datasync);
++ if (!err)
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ //hdir_unlock(h_inode, inode, bindex);
++ i_unlock(h_inode);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * @file may be NULL
++ */
++static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct inode *inode;
++ struct file *hidden_file;
++ struct super_block *sb;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ if (file) {
++ err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
++ /*locked*/1);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ } else
++ di_read_lock_child(dentry, !AUFS_I_WLOCK);
++
++ ii_write_lock_child(inode);
++ if (file) {
++ bend = fbend(file);
++ for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (!hidden_file || test_ro(sb, bindex, inode))
++ continue;
++
++ err = -EINVAL;
++ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++ // todo: try do_fsync() in fs/sync.c
++#if 0
++ DEBUG_ON(hidden_file->f_dentry->d_inode
++ != au_h_iptr_i(inode, bindex));
++ hdir_lock(hidden_file->f_dentry->d_inode, inode,
++ bindex);
++#else
++ i_lock(hidden_file->f_dentry->d_inode);
++#endif
++ err = hidden_file->f_op->fsync
++ (hidden_file, hidden_file->f_dentry,
++ datasync);
++ //err = -1;
++#if 0
++ hdir_unlock(hidden_file->f_dentry->d_inode,
++ inode, bindex);
++#else
++ i_unlock(hidden_file->f_dentry->d_inode);
++#endif
++ }
++ }
++ } else
++ err = fsync_dir(dentry, datasync);
++ au_cpup_attr_timesizes(inode);
++ ii_write_unlock(inode);
++ if (file)
++ fi_write_unlock(file);
++ else
++ di_read_unlock(dentry, !AUFS_I_WLOCK);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ au_nfsd_lockdep_off();
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
++ /*locked*/1);
++ if (unlikely(err))
++ goto out;
++
++ ii_write_lock_child(inode);
++ err = au_init_vdir(file);
++ if (unlikely(err)) {
++ ii_write_unlock(inode);
++ goto out_unlock;
++ }
++ //DbgVdir(fvdir_cache(file));// goto out_unlock;
++
++ /* nfsd filldir calls lookup_one_len(). */
++ ii_downgrade_lock(inode);
++ err = au_fill_de(file, dirent, filldir);
++ //DbgVdir(fvdir_cache(file));// goto out_unlock;
++
++ inode->i_atime = au_h_iptr(inode)->i_atime;
++ ii_read_unlock(inode);
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ au_nfsd_lockdep_on();
++#if 0 // debug
++ if (LktrCond)
++ igrab(inode);
++#endif
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct test_empty_arg {
++ struct aufs_nhash *whlist;
++ int whonly;
++ aufs_bindex_t bindex;
++ int err, called;
++};
++
++static int test_empty_cb(void *__arg, const char *__name, int namelen,
++ loff_t offset, filldir_ino_t ino, unsigned int d_type)
++{
++ struct test_empty_arg *arg = __arg;
++ char *name = (void*)__name;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ arg->err = 0;
++ arg->called++;
++ //smp_mb();
++ if (name[0] == '.'
++ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
++ return 0; /* success */
++
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (arg->whonly && !test_known_wh(arg->whlist, name, namelen))
++ arg->err = -ENOTEMPTY;
++ goto out;
++ }
++
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ if (!test_known_wh(arg->whlist, name, namelen))
++ arg->err = append_wh(arg->whlist, name, namelen, arg->bindex);
++
++ out:
++ //smp_mb();
++ TraceErr(arg->err);
++ return arg->err;
++}
++
++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err, dlgt;
++ struct file *hidden_file;
++
++ LKTRTrace("%.*s, {%p, %d, %d}\n",
++ DLNPair(dentry), arg->whlist, arg->whonly, arg->bindex);
++
++ hidden_file = hidden_open(dentry, arg->bindex,
++ O_RDONLY | O_NONBLOCK | O_DIRECTORY
++ | O_LARGEFILE);
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out;
++
++ dlgt = need_dlgt(dentry->d_sb);
++ //hidden_file->f_pos = 0;
++ do {
++ arg->err = 0;
++ arg->called = 0;
++ //smp_mb();
++ err = vfsub_readdir(hidden_file, test_empty_cb, arg, dlgt);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && arg->called);
++ fput(hidden_file);
++ sbr_put(dentry->d_sb, arg->bindex);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct do_test_empty_args {
++ int *errp;
++ struct dentry *dentry;
++ struct test_empty_arg *arg;
++};
++
++static void call_do_test_empty(void *args)
++{
++ struct do_test_empty_args *a = args;
++ *a->errp = do_test_empty(a->dentry, a->arg);
++}
++
++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err;
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ hidden_dentry = au_h_dptr_i(dentry, arg->bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode || !S_ISDIR(hidden_inode->i_mode));
++
++ hi_lock_child(hidden_inode);
++ err = au_test_perm(hidden_inode, MAY_EXEC | MAY_READ,
++ need_dlgt(dentry->d_sb));
++ i_unlock(hidden_inode);
++ if (!err)
++ err = do_test_empty(dentry, arg);
++ else {
++ struct do_test_empty_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .arg = arg
++ };
++ au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++int au_test_empty_lower(struct dentry *dentry)
++{
++ int err;
++ struct inode *inode;
++ struct test_empty_arg arg;
++ struct aufs_nhash *whlist;
++ aufs_bindex_t bindex, bstart, btail;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++
++ bstart = dbstart(dentry);
++ arg.whlist = whlist;
++ arg.whonly = 0;
++ arg.bindex = bstart;
++ err = do_test_empty(dentry, &arg);
++ if (unlikely(err))
++ goto out_whlist;
++
++ arg.whonly = 1;
++ btail = dbtaildir(dentry);
++ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
++ struct dentry *hidden_dentry;
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry && hidden_dentry->d_inode) {
++ DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
++ arg.bindex = bindex;
++ err = do_test_empty(dentry, &arg);
++ }
++ }
++
++ out_whlist:
++ nhash_del(whlist);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int test_empty(struct dentry *dentry, struct aufs_nhash *whlist)
++{
++ int err;
++ struct inode *inode;
++ struct test_empty_arg arg;
++ aufs_bindex_t bindex, btail;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ err = 0;
++ arg.whlist = whlist;
++ arg.whonly = 1;
++ btail = dbtaildir(dentry);
++ for (bindex = dbstart(dentry); !err && bindex <= btail; bindex++) {
++ struct dentry *hidden_dentry;
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry && hidden_dentry->d_inode) {
++ DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
++ arg.bindex = bindex;
++ err = sio_test_empty(dentry, &arg);
++ }
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_add_nlink(struct inode *dir, struct inode *h_dir)
++{
++ DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++ dir->i_nlink += h_dir->i_nlink - 2;
++ if (unlikely(h_dir->i_nlink < 2))
++ dir->i_nlink += 2;
++}
++
++void au_sub_nlink(struct inode *dir, struct inode *h_dir)
++{
++ DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++ dir->i_nlink -= h_dir->i_nlink - 2;
++ if (unlikely(h_dir->i_nlink < 2))
++ dir->i_nlink -= 2;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 // comment
++struct file_operations {
++ struct module *owner;
++ loff_t (*llseek) (struct file *, loff_t, int);
++ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
++ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
++ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
++ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
++ int (*readdir) (struct file *, void *, filldir_t);
++ unsigned int (*poll) (struct file *, struct poll_table_struct *);
++ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
++ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
++ long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
++ int (*mmap) (struct file *, struct vm_area_struct *);
++ int (*open) (struct inode *, struct file *);
++ int (*flush) (struct file *);
++ int (*release) (struct inode *, struct file *);
++ int (*fsync) (struct file *, struct dentry *, int datasync);
++ int (*aio_fsync) (struct kiocb *, int datasync);
++ int (*fasync) (int, struct file *, int);
++ int (*lock) (struct file *, int, struct file_lock *);
++ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
++ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
++ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
++ int (*check_flags)(int);
++ int (*dir_notify)(struct file *file, unsigned long arg);
++ int (*flock) (struct file *, int, struct file_lock *);
++};
++#endif
++
++struct file_operations aufs_dir_fop = {
++ .read = generic_read_dir,
++ .readdir = aufs_readdir,
++ .open = aufs_open_dir,
++ .release = aufs_release_dir,
++ .flush = aufs_flush,
++ .fsync = aufs_fsync_dir,
++};
+diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h
+new file mode 100755
+index 0000000..3ddf309
+--- /dev/null
++++ b/fs/aufs/dir.h
+@@ -0,0 +1,125 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dir.h,v 1.18 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DIR_H__
++#define __AUFS_DIR_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++#define filldir_ino_t u64
++#else
++#define filldir_ino_t ino_t
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* need to be faster and smaller */
++
++#define AUFS_DEBLK_SIZE 512 // todo: changable
++#define AUFS_NHASH_SIZE 32 // todo: changable
++#if AUFS_DEBLK_SIZE < NAME_MAX || PAGE_SIZE < AUFS_DEBLK_SIZE
++#error invalid size AUFS_DEBLK_SIZE
++#endif
++
++typedef char aufs_deblk_t[AUFS_DEBLK_SIZE];
++
++struct aufs_nhash {
++ struct hlist_head heads[AUFS_NHASH_SIZE];
++};
++
++struct aufs_destr {
++ unsigned char len;
++ char name[0];
++} __attribute__ ((packed));
++
++struct aufs_dehstr {
++ struct hlist_node hash;
++ struct aufs_destr *str;
++};
++
++struct aufs_de {
++ ino_t de_ino;
++ unsigned char de_type;
++ //caution: packed
++ struct aufs_destr de_str;
++} __attribute__ ((packed));
++
++struct aufs_wh {
++ struct hlist_node wh_hash;
++ aufs_bindex_t wh_bindex;
++ struct aufs_destr wh_str;
++} __attribute__ ((packed));
++
++union aufs_deblk_p {
++ unsigned char *p;
++ aufs_deblk_t *deblk;
++ struct aufs_de *de;
++};
++
++struct aufs_vdir {
++ aufs_deblk_t **vd_deblk;
++ int vd_nblk;
++ struct {
++ int i;
++ union aufs_deblk_p p;
++ } vd_last;
++
++ unsigned long vd_version;
++ unsigned long vd_jiffy;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dir.c */
++extern struct file_operations aufs_dir_fop;
++int au_test_empty_lower(struct dentry *dentry);
++int test_empty(struct dentry *dentry, struct aufs_nhash *whlist);
++void au_add_nlink(struct inode *dir, struct inode *h_dir);
++void au_sub_nlink(struct inode *dir, struct inode *h_dir);
++
++/* vdir.c */
++struct aufs_nhash *nhash_new(gfp_t gfp);
++void nhash_del(struct aufs_nhash *nhash);
++void nhash_init(struct aufs_nhash *nhash);
++void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src);
++void nhash_fin(struct aufs_nhash *nhash);
++int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit);
++int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen);
++int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
++ aufs_bindex_t bindex);
++void free_vdir(struct aufs_vdir *vdir);
++int au_init_vdir(struct file *file);
++int au_fill_de(struct file *file, void *dirent, filldir_t filldir);
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++unsigned int au_name_hash(const unsigned char *name, unsigned int len)
++{
++ return (full_name_hash(name, len) % AUFS_NHASH_SIZE);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DIR_H__ */
+diff --git a/fs/aufs/export.c b/fs/aufs/export.c
+new file mode 100755
+index 0000000..7b1c6ac
+--- /dev/null
++++ b/fs/aufs/export.c
+@@ -0,0 +1,585 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: export.c,v 1.7 2007/05/14 03:38:24 sfjro Exp $ */
++
++#include "aufs.h"
++
++extern struct export_operations export_op_default;
++#define CALL(ops, func) (((ops)->func) ? ((ops)->func) : export_op_default.func)
++#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED)
++
++union conv {
++#if BITS_PER_LONG == 32
++ __u32 a[1];
++#else
++ __u32 a[2];
++#endif
++ ino_t ino;
++};
++
++static ino_t decode_ino(__u32 *a)
++{
++ union conv u;
++ u.a[0] = a[0];
++#if BITS_PER_LONG == 64
++ u.a[1] = a[1];
++#endif
++ return u.ino;
++}
++
++static void encode_ino(__u32 *a, ino_t ino)
++{
++ union conv u;
++ u.ino = ino;
++ a[0] = u.a[0];
++#if BITS_PER_LONG == 64
++ a[1] = u.a[1];
++#endif
++}
++
++static void decode_br_id_sigen(__u32 a, aufs_bindex_t *br_id,
++ aufs_bindex_t *sigen)
++{
++ BUILD_BUG_ON((sizeof(*br_id) + sizeof(*sigen)) > sizeof(a));
++ *br_id = a >> 16;
++ DEBUG_ON(*br_id < 0);
++ *sigen = a;
++ DEBUG_ON(*sigen < 0);
++}
++
++static __u32 encode_br_id_sigen(aufs_bindex_t br_id, aufs_bindex_t sigen)
++{
++ DEBUG_ON(br_id < 0 || sigen < 0);
++ return (br_id << 16) | sigen;
++}
++
++/* NFS file handle */
++enum {
++ /* support 64bit inode number */
++ /* but untested */
++ Fh_br_id_sigen,
++ Fh_ino1,
++#if BITS_PER_LONG == 64
++ Fh_ino2,
++#endif
++ Fh_dir_ino1,
++#if BITS_PER_LONG == 64
++ Fh_dir_ino2,
++#endif
++ Fh_h_ino1,
++#if BITS_PER_LONG == 64
++ Fh_h_ino2,
++#endif
++ Fh_h_igen,
++ Fh_h_type,
++ Fh_tail,
++
++ Fh_ino = Fh_ino1,
++ Fh_dir_ino = Fh_dir_ino1,
++ Fh_h_ino = Fh_h_ino1,
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry;
++ struct inode *inode;
++
++ LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
++
++ dentry = NULL;
++ inode = ilookup(sb, ino);
++ if (unlikely(!inode))
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ dentry = NULL;
++ if (!S_ISDIR(inode->i_mode)) {
++ struct dentry *d;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias)
++ if (!is_anon(d)
++ && d->d_parent->d_inode->i_ino == dir_ino) {
++ dentry = dget_locked(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ } else {
++ dentry = d_find_alias(inode);
++ if (dentry
++ && !is_anon(dentry)
++ && dentry->d_parent->d_inode->i_ino == dir_ino)
++ goto out_iput; /* success */
++
++ dput(dentry);
++ dentry = NULL;
++ }
++
++ out_iput:
++ iput(inode);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct find_name_by_ino {
++ int called, found;
++ ino_t ino;
++ char *name;
++ int namelen;
++};
++
++static int
++find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
++ filldir_ino_t ino, unsigned int d_type)
++{
++ struct find_name_by_ino *a = arg;
++
++ a->called++;
++ if (a->ino != ino)
++ return 0;
++
++ memcpy(a->name, name, namelen);
++ a->namelen = namelen;
++ a->found = 1;
++ return 1;
++}
++
++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry, *parent;
++ struct inode *dir;
++ struct find_name_by_ino arg;
++ struct file *file;
++ int err;
++
++ LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
++
++ dentry = NULL;
++ dir = ilookup(sb, dir_ino);
++ if (unlikely(!dir))
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ if (unlikely(is_bad_inode(dir)))
++ goto out_iput;
++
++ dentry = NULL;
++ parent = d_find_alias(dir);
++ if (parent) {
++ if (unlikely(is_anon(parent))) {
++ dput(parent);
++ goto out_iput;
++ }
++ } else
++ goto out_iput;
++
++ file = dentry_open(parent, NULL, au_dir_roflags);
++ dentry = (void*)file;
++ if (IS_ERR(file))
++ goto out_iput;
++
++ dentry = ERR_PTR(-ENOMEM);
++ arg.name = __getname();
++ if (unlikely(!arg.name))
++ goto out_fput;
++ arg.ino = ino;
++ arg.found = 0;
++
++ do {
++ arg.called = 0;
++ //smp_mb();
++ err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
++ } while (!err && !arg.found && arg.called);
++ dentry = ERR_PTR(err);
++ if (arg.found) {
++ /* do not call lkup_one(), nor dlgt */
++ i_lock(dir);
++ dentry = lookup_one_len(arg.name, parent, arg.namelen);
++ i_unlock(dir);
++ TraceErrPtr(dentry);
++ }
++
++ //out_putname:
++ __putname(arg.name);
++ out_fput:
++ fput(file);
++ out_iput:
++ iput(dir);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct append_name {
++ int found, called, len;
++ char *h_path;
++ ino_t h_ino;
++};
++
++static int append_name(void *arg, const char *name, int len, loff_t pos,
++ filldir_ino_t ino, unsigned int d_type)
++{
++ struct append_name *a = arg;
++ char *p;
++
++ a->called++;
++ if (ino != a->h_ino)
++ return 0;
++
++ DEBUG_ON(len == 1 && *name == '.');
++ DEBUG_ON(len == 2 && name[0] == '.' && name[1] == '.');
++ a->len = strlen(a->h_path);
++ memmove(a->h_path - a->len - 1, a->h_path, a->len);
++ a->h_path -= a->len + 1;
++ p = a->h_path + a->len;
++ *p++ = '/';
++ memcpy(p, name, a->len);
++ a->len += 1 + len;
++ a->found++;
++ return 1;
++}
++
++static int h_acceptable(void *expv, struct dentry *dentry)
++{
++ return 1;
++}
++
++static struct dentry*
++decode_by_path(struct super_block *sb, aufs_bindex_t bindex, __u32 *fh,
++ int fh_len, void *context)
++{
++ struct dentry *dentry, *h_parent, *root, *h_root;
++ struct super_block *h_sb;
++ char *path, *p;
++ struct vfsmount *h_mnt;
++ struct append_name arg;
++ int len, err;
++ struct file *h_file;
++ struct nameidata nd;
++ struct aufs_branch *br;
++
++ LKTRTrace("b%d\n", bindex);
++ SiMustAnyLock(sb);
++
++ br = stobr(sb, bindex);
++ //br_get(br);
++ h_mnt = br->br_mnt;
++ h_sb = h_mnt->mnt_sb;
++ LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
++ h_parent = CALL(h_sb->s_export_op, decode_fh)
++ (h_sb, fh + Fh_tail, fh_len - Fh_tail, fh[Fh_h_type],
++ h_acceptable, /*context*/NULL);
++ dentry = h_parent;
++ if (unlikely(!h_parent || IS_ERR(h_parent))) {
++ Warn1("%s decode_fh failed\n", au_sbtype(h_sb));
++ goto out;
++ }
++ dentry = NULL;
++ if (unlikely(is_anon(h_parent))) {
++ Warn1("%s decode_fh returned a disconnected dentry\n",
++ au_sbtype(h_sb));
++ dput(h_parent);
++ goto out;
++ }
++
++ dentry = ERR_PTR(-ENOMEM);
++ path = __getname();
++ if (unlikely(!path)) {
++ dput(h_parent);
++ goto out;
++ }
++
++ root = sb->s_root;
++ di_read_lock_parent(root, !AUFS_I_RLOCK);
++ h_root = au_h_dptr_i(root, bindex);
++ di_read_unlock(root, !AUFS_I_RLOCK);
++ arg.h_path = d_path(h_root, h_mnt, path, PATH_MAX);
++ dentry = (void*)arg.h_path;
++ if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
++ goto out_putname;
++ len = strlen(arg.h_path);
++ arg.h_path = d_path(h_parent, h_mnt, path, PATH_MAX);
++ dentry = (void*)arg.h_path;
++ if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
++ goto out_putname;
++ LKTRTrace("%s\n", arg.h_path);
++ if (len != 1)
++ arg.h_path += len;
++ LKTRTrace("%s\n", arg.h_path);
++
++ /* cf. fs/exportfs/expfs.c */
++ h_file = dentry_open(h_parent, NULL, au_dir_roflags);
++ dentry = (void*)h_file;
++ if (IS_ERR(h_file))
++ goto out_putname;
++
++ arg.found = 0;
++ arg.h_ino = decode_ino(fh + Fh_h_ino);
++ do {
++ arg.called = 0;
++ err = vfsub_readdir(h_file, append_name, &arg, /*dlgt*/0);
++ } while (!err && !arg.found && arg.called);
++ LKTRTrace("%s, %d\n", arg.h_path, arg.len);
++
++ p = d_path(root, stosi(sb)->si_mnt, path, PATH_MAX - arg.len - 2);
++ dentry = (void*)p;
++ if (unlikely(!p || IS_ERR(p)))
++ goto out_fput;
++ p[strlen(p)] = '/';
++ LKTRTrace("%s\n", p);
++
++ err = path_lookup(p, LOOKUP_FOLLOW, &nd);
++ dentry = ERR_PTR(err);
++ if (!err) {
++ dentry = dget(nd.dentry);
++ if (unlikely(is_anon(dentry))) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ path_release(&nd);
++ }
++
++ out_fput:
++ fput(h_file);
++ out_putname:
++ __putname(path);
++ out:
++ //br_put(br);
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry*
++aufs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context)
++{
++ struct dentry *dentry;
++ ino_t ino, dir_ino;
++ aufs_bindex_t bindex, br_id, sigen_v;
++ struct inode *inode, *h_inode;
++
++ //au_debug_on();
++ LKTRTrace("%d, fh{i%u, br_id_sigen 0x%x, hi%u}\n",
++ fh_type, fh[Fh_ino], fh[Fh_br_id_sigen], fh[Fh_h_ino]);
++ DEBUG_ON(fh_len < Fh_tail);
++
++ si_read_lock(sb);
++ lockdep_off();
++
++ /* branch id may be wrapped around */
++ dentry = ERR_PTR(-ESTALE);
++ decode_br_id_sigen(fh[Fh_br_id_sigen], &br_id, &sigen_v);
++ bindex = find_brindex(sb, br_id);
++ if (unlikely(bindex < 0 || au_sigen(sb) < sigen_v))
++ goto out;
++
++ /* is this inode still cached? */
++ ino = decode_ino(fh + Fh_ino);
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ dentry = decode_by_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out;
++ if (dentry)
++ goto accept;
++
++ /* is the parent dir cached? */
++ dentry = decode_by_dir_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out;
++ if (dentry)
++ goto accept;
++
++ /* lookup path */
++ dentry = decode_by_path(sb, bindex, fh, fh_len, context);
++ if (IS_ERR(dentry))
++ goto out;
++ if (unlikely(!dentry))
++ goto out_stale;
++ if (unlikely(dentry->d_inode->i_ino != ino))
++ goto out_dput;
++
++ accept:
++ inode = dentry->d_inode;
++ h_inode = NULL;
++ ii_read_lock_child(inode);
++ if (ibstart(inode) <= bindex && bindex <= ibend(inode))
++ h_inode = au_h_iptr_i(inode, bindex);
++ ii_read_unlock(inode);
++ if (h_inode
++ && h_inode->i_generation == fh[Fh_h_igen]
++ && acceptable(context, dentry))
++ goto out; /* success */
++ out_dput:
++ dput(dentry);
++ out_stale:
++ dentry = ERR_PTR(-ESTALE);
++ out:
++ lockdep_on();
++ si_read_unlock(sb);
++ TraceErrPtr(dentry);
++ //au_debug_off();
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
++ int connectable)
++{
++ int err;
++ struct super_block *sb, *h_sb;
++ struct inode *inode, *h_inode, *dir;
++ aufs_bindex_t bindex;
++ union conv u;
++ struct dentry *parent, *h_parent;
++
++ //au_debug_on();
++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
++ LKTRTrace("%.*s, max %d, conn %d\n",
++ DLNPair(dentry), *max_len, connectable);
++ DEBUG_ON(is_anon(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode);
++ parent = dentry->d_parent;
++ DEBUG_ON(is_anon(parent));
++
++ err = -ENOSPC;
++ if (unlikely(*max_len <= Fh_tail)) {
++ Warn1("NFSv2 client (max_len %d)?\n", *max_len);
++ goto out;
++ }
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++#ifdef CONFIG_AUFS_DEBUG
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ Warn1("NFS-exporting requires xino\n");
++#if 0
++ if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ Warn1("udba=inotify is not recommended when exporting\n");
++#endif
++#endif
++
++ err = -EPERM;
++ bindex = ibstart(inode);
++ h_sb = sbr_sb(sb, bindex);
++ if (unlikely(!h_sb->s_export_op)) {
++ Err1("%s branch is not exportable\n", au_sbtype(h_sb));
++ goto out_unlock;
++ }
++
++#if 0 //def CONFIG_AUFS_ROBR
++ if (unlikely(SB_AUFS(h_sb))) {
++ Err1("aufs branch is not supported\n");
++ goto out_unlock;
++ }
++#endif
++
++ /* doesn't support pseudo-link */
++ if (unlikely(bindex < dbstart(dentry)
++ || dbend(dentry) < bindex
++ || !au_h_dptr_i(dentry, bindex))) {
++ Err("%.*s/%.*s, b%d, pseudo-link?\n",
++ DLNPair(dentry->d_parent), DLNPair(dentry), bindex);
++ goto out_unlock;
++ }
++
++ fh[Fh_br_id_sigen] = encode_br_id_sigen(sbr_id(sb, bindex),
++ au_sigen(sb));
++ encode_ino(fh + Fh_ino, inode->i_ino);
++ dir = parent->d_inode;
++ encode_ino(fh + Fh_dir_ino, dir->i_ino);
++ h_inode = au_h_iptr(inode);
++ encode_ino(fh + Fh_h_ino, h_inode->i_ino);
++ fh[Fh_h_igen] = h_inode->i_generation;
++
++ /* it should be set at exporting time */
++ if (unlikely(!h_sb->s_export_op->find_exported_dentry)) {
++ Warn("set default find_exported_dentry for %s\n",
++ au_sbtype(h_sb));
++ h_sb->s_export_op->find_exported_dentry = find_exported_dentry;
++ }
++
++ *max_len -= Fh_tail;
++ //LKTRTrace("Fh_tail %d, max_len %d\n", Fh_tail, *max_len);
++ h_parent = au_h_dptr_i(parent, bindex);
++ DEBUG_ON(is_anon(h_parent));
++ err = fh[Fh_h_type] = CALL(h_sb->s_export_op, encode_fh)
++ (h_parent, fh + Fh_tail, max_len, connectable);
++ *max_len += Fh_tail;
++ if (err != 255)
++ err = 2; //??
++ else
++ Warn1("%s encode_fh failed\n", au_sbtype(h_sb));
++
++ out_unlock:
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ out:
++ TraceErr(err);
++ //au_debug_off();
++ if (unlikely(err < 0))
++ err = 255;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0
++struct export_operations {
++ struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context);
++ int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
++ int connectable);
++
++ /* the following are only called from the filesystem itself */
++ int (*get_name)(struct dentry *parent, char *name,
++ struct dentry *child);
++ struct dentry * (*get_parent)(struct dentry *child);
++ struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
++
++ /* This is set by the exporting module to a standard helper */
++ struct dentry * (*find_exported_dentry)(
++ struct super_block *sb, void *obj, void *parent,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context);
++};
++#endif
++
++struct export_operations aufs_export_op = {
++ .decode_fh = aufs_decode_fh,
++ .encode_fh = aufs_encode_fh
++};
+diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
+new file mode 100755
+index 0000000..3cd1081
+--- /dev/null
++++ b/fs/aufs/f_op.c
+@@ -0,0 +1,684 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: f_op.c,v 1.27 2007/05/14 03:38:24 sfjro Exp $ */
++
++#include <linux/fsnotify.h>
++#include <linux/pagemap.h>
++#include <linux/poll.h>
++#include <linux/security.h>
++#include <linux/version.h>
++#include "aufs.h"
++
++/* common function to regular file and dir */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#define FlushArgs hidden_file, id
++int aufs_flush(struct file *file, fl_owner_t id)
++#else
++#define FlushArgs hidden_file
++int aufs_flush(struct file *file)
++#endif
++{
++ int err;
++ struct dentry *dentry;
++ aufs_bindex_t bindex, bend;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ // aufs_read_lock_file()
++ si_read_lock(dentry->d_sb);
++ fi_read_lock(file);
++ di_read_lock_child(dentry, !AUFS_I_RLOCK);
++
++ err = 0;
++ bend = fbend(file);
++ for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
++ struct file *hidden_file;
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (hidden_file && hidden_file->f_op
++ && hidden_file->f_op->flush)
++ err = hidden_file->f_op->flush(FlushArgs);
++ }
++
++ di_read_unlock(dentry, !AUFS_I_RLOCK);
++ fi_read_unlock(file);
++ si_read_unlock(dentry->d_sb);
++ TraceErr(err);
++ return err;
++}
++#undef FlushArgs
++
++/* ---------------------------------------------------------------------- */
++
++static int do_open_nondir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct super_block *sb;
++ struct file *hidden_file;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_finfo *finfo;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, flags 0%o\n", DLNPair(dentry), flags);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || S_ISDIR(inode->i_mode));
++
++ err = 0;
++ finfo = ftofi(file);
++ finfo->fi_h_vm_ops = NULL;
++ sb = dentry->d_sb;
++ bindex = dbstart(dentry);
++ DEBUG_ON(!au_h_dptr(dentry)->d_inode);
++ /* O_TRUNC is processed already */
++ BUG_ON(test_ro(sb, bindex, inode) && (flags & O_TRUNC));
++
++ hidden_file = hidden_open(dentry, bindex, flags);
++ //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bindex));
++ //hidden_file = ERR_PTR(-1);}
++ if (!IS_ERR(hidden_file)) {
++ set_fbstart(file, bindex);
++ set_fbend(file, bindex);
++ set_h_fptr(file, bindex, hidden_file);
++ return 0; /* success */
++ }
++ err = PTR_ERR(hidden_file);
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_open_nondir(struct inode *inode, struct file *file)
++{
++ return au_do_open(inode, file, do_open_nondir);
++}
++
++static int aufs_release_nondir(struct inode *inode, struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
++
++ si_read_lock(sb);
++ au_fin_finfo(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct file *hidden_file;
++ struct super_block *sb;
++ struct inode *h_inode;
++ int dlgt;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(dentry), (unsigned long)count, *ppos);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //if (LktrCond) {fi_read_unlock(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ /* support LSM and notify */
++ dlgt = need_dlgt(sb);
++ hidden_file = au_h_fptr(file);
++ h_inode = hidden_file->f_dentry->d_inode;
++ if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
++ err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
++ else {
++ struct inode *dir = dentry->d_parent->d_inode,
++ *h_dir = hidden_file->f_dentry->d_parent->d_inode;
++ aufs_bindex_t bstart = fbstart(file);
++ hdir_lock(h_dir, dir, bstart);
++ err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
++ hdir_unlock(h_dir, dir, bstart);
++ }
++ memcpy(&file->f_ra, &hidden_file->f_ra, sizeof(file->f_ra)); //??
++ dentry->d_inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
++
++ fi_read_unlock(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++static ssize_t aufs_write(struct file *file, const char __user *__buf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *hidden_file;
++ char __user *buf = (char __user*)__buf;
++ struct inode *h_inode;
++ int dlgt;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(dentry), (unsigned long)count, *ppos);
++
++ inode = dentry->d_inode;
++ i_lock(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
++ /*locked*/1);
++ //if (LktrCond) {fi_write_unlock(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++ err = au_ready_to_write(file, -1);
++ //if (LktrCond) err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* support LSM and notify */
++ dlgt = need_dlgt(sb);
++ hidden_file = au_h_fptr(file);
++ h_inode = hidden_file->f_dentry->d_inode;
++ if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
++ err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
++ else {
++ struct inode *dir = dentry->d_parent->d_inode,
++ *h_dir = hidden_file->f_dentry->d_parent->d_inode;
++ aufs_bindex_t bstart = fbstart(file);
++ hdir_lock(h_dir, dir, bstart);
++ err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
++ hdir_unlock(h_dir, dir, bstart);
++ }
++ ii_write_lock_child(inode);
++ au_cpup_attr_timesizes(inode);
++ ii_write_unlock(inode);
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ i_unlock(inode);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 //def CONFIG_AUFS_ROBR
++struct lvma {
++ struct list_head list;
++ struct vm_area_struct *vma;
++};
++
++static struct file *safe_file(struct vm_area_struct *vma)
++{
++ struct file *file = vma->vm_file;
++ struct super_block *sb = file->f_dentry->d_sb;
++ struct lvma *lvma, *entry;
++ struct aufs_sbinfo *sbinfo;
++ int found, warn;
++
++ TraceEnter();
++ DEBUG_ON(!SB_AUFS(sb));
++
++ warn = 0;
++ found = 0;
++ sbinfo = stosi(sb);
++ spin_lock(&sbinfo->si_lvma_lock);
++ list_for_each_entry(entry, &sbinfo->si_lvma, list) {
++ found = (entry->vma == vma);
++ if (unlikely(found))
++ break;
++ }
++ if (!found) {
++ lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
++ if (lvma) {
++ lvma->vma = vma;
++ list_add(&lvma->list, &sbinfo->si_lvma);
++ } else {
++ warn = 1;
++ file = NULL;
++ }
++ } else
++ file = NULL;
++ spin_unlock(&sbinfo->si_lvma_lock);
++
++ if (unlikely(warn))
++ Warn1("no memory for lvma\n");
++ return file;
++}
++
++static void reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++ struct lvma *entry, *found;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ DEBUG_ON(!SB_AUFS(sb));
++
++ vma->vm_file = file;
++
++ found = NULL;
++ sbinfo = stosi(sb);
++ spin_lock(&sbinfo->si_lvma_lock);
++ list_for_each_entry(entry, &sbinfo->si_lvma, list)
++ if (entry->vma == vma){
++ found = entry;
++ break;
++ }
++ DEBUG_ON(!found);
++ list_del(&found->list);
++ spin_unlock(&sbinfo->si_lvma_lock);
++ kfree(found);
++}
++
++#else
++
++static struct file *safe_file(struct vm_area_struct *vma)
++{
++ struct file *file;
++
++ file = vma->vm_file;
++ if (file->private_data && au_is_aufs(file->f_dentry->d_sb))
++ return file;
++ return NULL;
++}
++
++static void reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ vma->vm_file = file;
++ smp_mb();
++}
++#endif /* CONFIG_AUFS_ROBR */
++
++static struct page *aufs_nopage(struct vm_area_struct *vma, unsigned long addr,
++ int *type)
++{
++ struct page *page;
++ struct dentry *dentry;
++ struct file *file, *hidden_file;
++ struct inode *inode;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct aufs_finfo *finfo;
++
++ TraceEnter();
++ DEBUG_ON(!vma || !vma->vm_file);
++ wait_event(wq, (file = safe_file(vma)));
++ DEBUG_ON(!au_is_aufs(file->f_dentry->d_sb));
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, addr %lx\n", DLNPair(dentry), addr);
++ inode = dentry->d_inode;
++ DEBUG_ON(!S_ISREG(inode->i_mode));
++
++ // do not revalidate, nor lock
++ finfo = ftofi(file);
++ hidden_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ DEBUG_ON(!hidden_file || !au_is_mmapped(file));
++ vma->vm_file = hidden_file;
++ //smp_mb();
++ page = finfo->fi_h_vm_ops->nopage(vma, addr, type);
++ reset_file(vma, file);
++#if 0 //def CONFIG_SMP
++ //wake_up_nr(&wq, online_cpu - 1);
++ wake_up_all(&wq);
++#else
++ wake_up(&wq);
++#endif
++ if (!IS_ERR(page)) {
++ //page->mapping = file->f_mapping;
++ //get_page(page);
++ //file->f_mapping = hidden_file->f_mapping;
++ //touch_atime(NULL, dentry);
++ //inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
++ }
++ TraceErrPtr(page);
++ return page;
++}
++
++static int aufs_populate(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long len, pgprot_t prot, unsigned long pgoff,
++ int nonblock)
++{
++ Err("please report me this application\n");
++ BUG();
++ return ftofi(vma->vm_file)->fi_h_vm_ops->populate
++ (vma, addr, len, prot, pgoff, nonblock);
++}
++
++static struct vm_operations_struct aufs_vm_ops = {
++ //.open = aufs_vmaopen,
++ //.close = aufs_vmaclose,
++ .nopage = aufs_nopage,
++ .populate = aufs_populate,
++ //page_mkwrite(struct vm_area_struct *vma, struct page *page)
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err, wlock, mmapped;
++ struct dentry *dentry;
++ struct super_block *sb;
++ struct file *h_file;
++ struct vm_operations_struct *vm_ops;
++ unsigned long flags;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, %lx, len %lu\n",
++ DLNPair(dentry), vma->vm_start, vma->vm_end - vma->vm_start);
++ DEBUG_ON(!S_ISREG(dentry->d_inode->i_mode));
++ DEBUG_ON(down_write_trylock(&vma->vm_mm->mmap_sem));
++
++ mmapped = au_is_mmapped(file);
++ wlock = 0;
++ if (file->f_mode & FMODE_WRITE) {
++ flags = VM_SHARED | VM_WRITE;
++ wlock = ((flags & vma->vm_flags) == flags);
++ }
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir,
++ wlock | !mmapped, /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ if (wlock) {
++ err = au_ready_to_write(file, -1);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ }
++
++ h_file = au_h_fptr(file);
++ vm_ops = ftofi(file)->fi_h_vm_ops;
++ if (unlikely(!mmapped)) {
++ // nfs uses some locks
++ lockdep_off();
++ err = h_file->f_op->mmap(h_file, vma);
++ lockdep_on();
++ if (unlikely(err))
++ goto out_unlock;
++ vm_ops = vma->vm_ops;
++ DEBUG_ON(!vm_ops);
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (unlikely(err)) {
++ IOErr("failed internal unmapping %.*s, %d\n",
++ DLNPair(h_file->f_dentry), err);
++ err = -EIO;
++ goto out_unlock;
++ }
++ }
++ DEBUG_ON(!vm_ops);
++
++ err = generic_file_mmap(file, vma);
++ if (!err) {
++ file_accessed(h_file);
++ dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
++ vma->vm_ops = &aufs_vm_ops;
++ if (unlikely(!mmapped))
++ ftofi(file)->fi_h_vm_ops = vm_ops;
++ }
++
++ out_unlock:
++ if (!wlock && mmapped)
++ fi_read_unlock(file);
++ else
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++// todo: try do_sendfile() in fs/read_write.c
++static ssize_t aufs_sendfile(struct file *file, loff_t *ppos,
++ size_t count, read_actor_t actor, void *target)
++{
++ ssize_t err;
++ struct file *h_file;
++ const char c = current->comm[4];
++ /* true if a kernel thread named 'loop[0-9].*' accesses a file */
++ const int loopback = (current->mm == NULL
++ && '0' <= c && c <= '9'
++ && strncmp(current->comm, "loop", 4) == 0);
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld, cnt %lu, loopback %d\n",
++ DLNPair(dentry), *ppos, (unsigned long)count, loopback);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ if (unlikely(err))
++ goto out;
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file);
++ if (h_file->f_op && h_file->f_op->sendfile) {
++ if (/* unlikely */(loopback)) {
++ file->f_mapping = h_file->f_mapping;
++ smp_mb(); //??
++ }
++ // nfs uses some locks
++ lockdep_off();
++ err = h_file->f_op->sendfile
++ (h_file, ppos, count, actor, target);
++ lockdep_on();
++ dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
++ }
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* copied from linux/fs/select.h, must match */
++#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
++
++static unsigned int aufs_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask;
++ struct file *hidden_file;
++ int err;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, wait %p\n", DLNPair(dentry), wait);
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode));
++
++ /* We should pretend an error happend. */
++ mask = POLLERR /* | POLLIN | POLLOUT */;
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ /* it is not an error of hidden_file has no operation */
++ mask = DEFAULT_POLLMASK;
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->poll)
++ mask = hidden_file->f_op->poll(hidden_file, wait);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr((int)mask);
++ return mask;
++}
++
++static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err, my_lock;
++ struct inode *inode;
++ struct file *hidden_file;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ inode = dentry->d_inode;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++ IMustLock(inode);
++ my_lock = 0;
++#else
++ /* before 2.6.17,
++ * msync(2) calls me without locking i_sem/i_mutex, but fsync(2).
++ */
++ my_lock = !i_trylock(inode);
++#endif
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = 0; //-EBADF; // posix?
++ if (unlikely(!(file->f_mode & FMODE_WRITE)))
++ goto out;
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
++ /*locked*/1);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ err = au_ready_to_write(file, -1);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++
++ err = -EINVAL;
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++ // todo: apparmor thread?
++ //file->f_mapping->host->i_mutex
++ ii_write_lock_child(inode);
++ hi_lock_child(hidden_file->f_dentry->d_inode);
++ err = hidden_file->f_op->fsync
++ (hidden_file, hidden_file->f_dentry, datasync);
++ //err = -1;
++ au_cpup_attr_timesizes(inode);
++ i_unlock(hidden_file->f_dentry->d_inode);
++ ii_write_unlock(inode);
++ }
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ if (unlikely(my_lock))
++ i_unlock(inode);
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_fasync(int fd, struct file *file, int flag)
++{
++ int err;
++ struct file *hidden_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), flag);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->fasync)
++ err = hidden_file->f_op->fasync(fd, hidden_file, flag);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 // comment
++struct file_operations {
++ struct module *owner;
++ loff_t (*llseek) (struct file *, loff_t, int);
++ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
++ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
++ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
++ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
++ int (*readdir) (struct file *, void *, filldir_t);
++ unsigned int (*poll) (struct file *, struct poll_table_struct *);
++ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
++ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
++ long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
++ int (*mmap) (struct file *, struct vm_area_struct *);
++ int (*open) (struct inode *, struct file *);
++ int (*flush) (struct file *);
++ int (*release) (struct inode *, struct file *);
++ int (*fsync) (struct file *, struct dentry *, int datasync);
++ int (*aio_fsync) (struct kiocb *, int datasync);
++ int (*fasync) (int, struct file *, int);
++ int (*lock) (struct file *, int, struct file_lock *);
++ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
++ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
++ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
++ int (*check_flags)(int);
++ int (*dir_notify)(struct file *file, unsigned long arg);
++ int (*flock) (struct file *, int, struct file_lock *);
++};
++#endif
++
++struct file_operations aufs_file_fop = {
++ .read = aufs_read,
++ .write = aufs_write,
++ .poll = aufs_poll,
++ .mmap = aufs_mmap,
++ .open = aufs_open_nondir,
++ .flush = aufs_flush,
++ .release = aufs_release_nondir,
++ .fsync = aufs_fsync_nondir,
++ .fasync = aufs_fasync,
++ .sendfile = aufs_sendfile,
++};
+diff --git a/fs/aufs/file.c b/fs/aufs/file.c
+new file mode 100755
+index 0000000..857a4e8
+--- /dev/null
++++ b/fs/aufs/file.c
+@@ -0,0 +1,832 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: file.c,v 1.42 2007/05/14 03:39:09 sfjro Exp $ */
++
++//#include <linux/fsnotify.h>
++#include <linux/pagemap.h>
++//#include <linux/poll.h>
++//#include <linux/security.h>
++#include "aufs.h"
++
++/* drop flags for writing */
++unsigned int au_file_roflags(unsigned int flags)
++{
++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
++ flags |= O_RDONLY | O_NOATIME;
++ return flags;
++}
++
++/* common functions to regular file and dir */
++struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
++{
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++ struct super_block *sb;
++ struct vfsmount *hidden_mnt;
++ struct file *hidden_file;
++ struct aufs_branch *br;
++ loff_t old_size;
++ int udba;
++
++ LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
++ DEBUG_ON(!dentry);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ sb = dentry->d_sb;
++ udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++ if (unlikely(udba)) {
++ // test here?
++ }
++
++ br = stobr(sb, bindex);
++ br_get(br);
++ /* drop flags for writing */
++ if (test_ro(sb, bindex, dentry->d_inode))
++ flags = au_file_roflags(flags);
++ flags &= ~O_CREAT;
++ spin_lock(&hidden_inode->i_lock);
++ old_size = i_size_read(hidden_inode);
++ spin_unlock(&hidden_inode->i_lock);
++
++ //DbgSleep(3);
++
++ dget(hidden_dentry);
++ hidden_mnt = mntget(br->br_mnt);
++ hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
++ //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}
++
++ if (!IS_ERR(hidden_file)) {
++#if 0 // remove this
++ if (/* old_size && */ (flags & O_TRUNC)) {
++ au_direval_dec(dentry);
++ if (!IS_ROOT(dentry))
++ au_direval_dec(dentry->d_parent);
++ }
++#endif
++ return hidden_file;
++ }
++
++ br_put(br);
++ TraceErrPtr(hidden_file);
++ return hidden_file;
++}
++
++static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
++{
++ int err;
++ struct dentry *parent, *h_parent, *h_dentry;
++ aufs_bindex_t bcpup;
++ struct inode *h_dir, *h_inode, *dir;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(IS_ROOT(dentry));
++ DiMustWriteLock(dentry);
++
++ parent = dentry->d_parent; // dget_parent()
++ di_write_lock_parent(parent);
++ bcpup = err = find_rw_parent_br(dentry, bstart);
++ //bcpup = err = find_rw_br(sb, bstart);
++ if (unlikely(err < 0)) {
++ err = 0; // stop copyup, it is not an error
++ goto out;
++ }
++ err = 0;
++
++ h_parent = au_h_dptr_i(parent, bcpup);
++ if (!h_parent) {
++ err = cpup_dirs(dentry, bcpup, NULL);
++ if (unlikely(err))
++ goto out;
++ h_parent = au_h_dptr_i(parent, bcpup);
++ }
++
++ h_dir = h_parent->d_inode;
++ h_dentry = au_h_dptr_i(dentry, bstart);
++ h_inode = h_dentry->d_inode;
++ dir = parent->d_inode;
++ hdir_lock(h_dir, dir, bcpup);
++ hi_lock_child(h_inode);
++ DEBUG_ON(au_h_dptr_i(dentry, bcpup));
++ err = sio_cpup_simple(dentry, bcpup, -1,
++ au_flags_cpup(CPUP_DTIME, parent));
++ TraceErr(err);
++ i_unlock(h_inode);
++ hdir_unlock(h_dir, dir, bcpup);
++
++ out:
++ di_write_unlock(parent);
++ TraceErr(err);
++ return err;
++}
++
++int au_do_open(struct inode *inode, struct file *file,
++ int (*open)(struct file *file, int flags))
++{
++ int err, coo;
++ struct dentry *dentry;
++ struct super_block *sb;
++ aufs_bindex_t bstart;
++ struct inode *h_dir, *dir;
++
++ dentry = file->f_dentry;
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ coo = 0;
++#if 0
++ switch (au_flag_test_coo(sb)) {
++ case AuFlag_COO_LEAF:
++ coo = !S_ISDIR(inode->i_mode);
++ break;
++ case AuFlag_COO_ALL:
++ coo = 1;
++ break;
++ }
++#endif
++ err = au_init_finfo(file);
++ //if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ if (!coo) {
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ bstart = dbstart(dentry);
++ } else {
++ di_write_lock_child(dentry);
++ bstart = dbstart(dentry);
++ if (test_ro(sb, bstart, dentry->d_inode)) {
++ err = do_coo(dentry, bstart);
++ if (err) {
++ di_write_unlock(dentry);
++ goto out_finfo;
++ }
++ bstart = dbstart(dentry);
++ }
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ }
++
++ // todo: remove this extra locks
++ dir = dentry->d_parent->d_inode;
++ if (!IS_ROOT(dentry))
++ ii_read_lock_parent(dir);
++ h_dir = au_h_iptr_i(dir, bstart);
++ hdir_lock(h_dir, dir, bstart);
++ err = open(file, file->f_flags);
++ //if (LktrCond) err = -1;
++ hdir_unlock(h_dir, dir, bstart);
++ if (!IS_ROOT(dentry))
++ ii_read_unlock(dir);
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++
++ out_finfo:
++ fi_write_unlock(file);
++ if (unlikely(err))
++ au_fin_finfo(file);
++ //DbgFile(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++int au_reopen_nondir(struct file *file)
++{
++ int err;
++ struct dentry *dentry;
++ aufs_bindex_t bstart, bindex, bend;
++ struct file *hidden_file, *h_file_tmp;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
++ || !au_h_dptr(dentry)->d_inode);
++ bstart = dbstart(dentry);
++
++ h_file_tmp = NULL;
++ if (fbstart(file) == bstart) {
++ hidden_file = au_h_fptr(file);
++ if (file->f_mode == hidden_file->f_mode)
++ return 0; /* success */
++ h_file_tmp = hidden_file;
++ get_file(h_file_tmp);
++ set_h_fptr(file, bstart, NULL);
++ }
++ DEBUG_ON(fbstart(file) < bstart
++ || ftofi(file)->fi_hfile[0 + bstart].hf_file);
++
++ hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC);
++ //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart));
++ //hidden_file = ERR_PTR(-1);}
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out; // close all?
++ err = 0;
++ //cpup_file_flags(hidden_file, file);
++ set_fbstart(file, bstart);
++ set_h_fptr(file, bstart, hidden_file);
++ memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //??
++
++ /* close lower files */
++ bend = fbend(file);
++ for (bindex = bstart + 1; bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++ set_fbend(file, bstart);
++
++ out:
++ if (h_file_tmp)
++ fput(h_file_tmp);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the deleted file for writing.
++ */
++static int cpup_wh_file(struct file *file, aufs_bindex_t bdst, loff_t len)
++{
++ int err;
++ struct dentry *dentry, *parent, *hidden_parent, *tmp_dentry;
++ struct dentry *hidden_dentry_bstart, *hidden_dentry_bdst;
++ struct inode *hidden_dir;
++ aufs_bindex_t bstart;
++ struct aufs_dinfo *dinfo;
++ struct dtime dt;
++ struct lkup_args lkup;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, bdst %d, len %Lu\n", DLNPair(dentry), bdst, len);
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE));
++ DiMustWriteLock(dentry);
++ parent = dentry->d_parent;
++ IiMustAnyLock(parent->d_inode);
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ DEBUG_ON(!hidden_parent);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!hidden_dir);
++ IMustLock(hidden_dir);
++
++ sb = parent->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bdst);
++ lkup.dlgt = need_dlgt(sb);
++ tmp_dentry = lkup_whtmp(hidden_parent, &dentry->d_name, &lkup);
++ //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(tmp_dentry);
++ if (IS_ERR(tmp_dentry))
++ goto out;
++
++ dtime_store(&dt, parent, hidden_parent);
++ dinfo = dtodi(dentry);
++ bstart = dinfo->di_bstart;
++ hidden_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
++ hidden_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
++ dinfo->di_bstart = bdst;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = tmp_dentry;
++ dinfo->di_hdentry[0 + bstart].hd_dentry = au_h_fptr(file)->f_dentry;
++ err = cpup_single(dentry, bdst, bstart, len,
++ au_flags_cpup(!CPUP_DTIME, parent));
++ //if (LktrCond) err = -1;
++ if (!err)
++ err = au_reopen_nondir(file);
++ //err = -1;
++ dinfo->di_hdentry[0 + bstart].hd_dentry = hidden_dentry_bstart;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = hidden_dentry_bdst;
++ dinfo->di_bstart = bstart;
++ if (unlikely(err))
++ goto out_tmp;
++
++ DEBUG_ON(!d_unhashed(dentry));
++ err = vfsub_unlink(hidden_dir, tmp_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1;
++ if (unlikely(err)) {
++ IOErr("failed remove copied-up tmp file %.*s(%d)\n",
++ DLNPair(tmp_dentry), err);
++ err = -EIO;
++ }
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++
++ out_tmp:
++ dput(tmp_dentry);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_wh_file_args {
++ int *errp;
++ struct file *file;
++ aufs_bindex_t bdst;
++ loff_t len;
++};
++
++static void call_cpup_wh_file(void *args)
++{
++ struct cpup_wh_file_args *a = args;
++ *a->errp = cpup_wh_file(a->file, a->bdst, a->len);
++}
++
++/*
++ * prepare the @file for writing.
++ */
++int au_ready_to_write(struct file *file, loff_t len)
++{
++ int err;
++ struct dentry *dentry, *parent, *hidden_dentry, *hidden_parent;
++ struct inode *hidden_inode, *hidden_dir, *inode, *dir;
++ struct super_block *sb;
++ aufs_bindex_t bstart, bcpup;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, len %Ld\n", DLNPair(dentry), len);
++ FiMustWriteLock(file);
++
++ sb = dentry->d_sb;
++ bstart = fbstart(file);
++ DEBUG_ON(ftobr(file, bstart) != stobr(sb, bstart));
++
++ inode = dentry->d_inode;
++ ii_read_lock_child(inode);
++ LKTRTrace("rdonly %d, bstart %d\n", test_ro(sb, bstart, inode), bstart);
++ err = test_ro(sb, bstart, inode);
++ ii_read_unlock(inode);
++ if (!err && (au_h_fptr(file)->f_mode & FMODE_WRITE))
++ return 0;
++
++ /* need to cpup */
++ parent = dentry->d_parent; // dget_parent()
++ di_write_lock_child(dentry);
++ di_write_lock_parent(parent);
++ bcpup = err = find_rw_parent_br(dentry, bstart);
++ //bcpup = err = find_rw_br(sb, bstart);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ err = 0;
++
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ if (!hidden_parent) {
++ err = cpup_dirs(dentry, bcpup, NULL);
++ //if (LktrCond) err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ }
++
++ hidden_dir = hidden_parent->d_inode;
++ hidden_dentry = au_h_fptr(file)->f_dentry;
++ hidden_inode = hidden_dentry->d_inode;
++ dir = parent->d_inode;
++ hdir_lock(hidden_dir, dir, bcpup);
++ hi_lock_child(hidden_inode);
++ if (d_unhashed(dentry) || d_unhashed(hidden_dentry)
++ /* || !hidden_inode->i_nlink */) {
++ if (!au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE,
++ need_dlgt(sb)))
++ err = cpup_wh_file(file, bcpup, len);
++ else {
++ struct cpup_wh_file_args args = {
++ .errp = &err,
++ .file = file,
++ .bdst = bcpup,
++ .len = len
++ };
++ au_wkq_wait(call_cpup_wh_file, &args, /*dlgt*/0);
++ }
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ } else {
++ if (!au_h_dptr_i(dentry, bcpup))
++ err = sio_cpup_simple(dentry, bcpup, len,
++ au_flags_cpup(CPUP_DTIME,
++ parent));
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ if (!err)
++ err = au_reopen_nondir(file);
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ }
++ i_unlock(hidden_inode);
++ hdir_unlock(hidden_dir, dir, bcpup);
++
++ out_unlock:
++ di_write_unlock(parent);
++ di_write_unlock(dentry);
++// out:
++ TraceErr(err);
++ return err;
++
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * after branch manipulating, refresh the file.
++ */
++static int refresh_file(struct file *file, int (*reopen)(struct file *file))
++{
++ int err, new_sz;
++ struct dentry *dentry;
++ aufs_bindex_t bend, bindex, bstart, brid;
++ struct aufs_hfile *p;
++ struct aufs_finfo *finfo;
++ struct super_block *sb;
++ struct inode *inode;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ FiMustWriteLock(file);
++ DiMustReadLock(dentry);
++ inode = dentry->d_inode;
++ IiMustReadLock(inode);
++ //au_debug_on();
++ //DbgDentry(dentry);
++ //DbgFile(file);
++ //au_debug_off();
++
++ err = -ENOMEM;
++ sb = dentry->d_sb;
++ finfo = ftofi(file);
++ bstart = finfo->fi_bstart;
++ bend = finfo->fi_bstart;
++ new_sz = sizeof(*finfo->fi_hfile) * (sbend(sb) + 1);
++ p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++ finfo->fi_hfile = p;
++ hidden_file = p[0 + bstart].hf_file;
++
++ p = finfo->fi_hfile + finfo->fi_bstart;
++ brid = p->hf_br->br_id;
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
++ struct aufs_hfile tmp, *q;
++ aufs_bindex_t new_bindex;
++
++ if (!p->hf_file)
++ continue;
++ new_bindex = find_bindex(sb, p->hf_br);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) { // test here
++ set_h_fptr(file, bindex, NULL);
++ continue;
++ }
++
++ /* swap two hidden inode, and loop again */
++ q = finfo->fi_hfile + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hf_file) {
++ bindex--;
++ p--;
++ }
++ }
++ {
++ aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
++ finfo->fi_bstart = 0;
++ finfo->fi_bend = sbend(sb);
++ //au_debug_on();
++ //DbgFile(file);
++ //au_debug_off();
++ finfo->fi_bstart = s;
++ finfo->fi_bend = e;
++ }
++
++ p = finfo->fi_hfile;
++ if (!au_is_mmapped(file) && !d_unhashed(dentry)) {
++ bend = sbend(sb);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p);
++ }
++ } else {
++ bend = find_brindex(sb, brid);
++ //LKTRTrace("%d\n", bend);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file)
++ au_hfput(p);
++ //LKTRTrace("%d\n", finfo->fi_bstart);
++ bend = sbend(sb);
++ }
++
++ p = finfo->fi_hfile + bend;
++ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
++ finfo->fi_bend--, p--)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p);
++ }
++ //Dbg("%d, %d\n", finfo->fi_bstart, finfo->fi_bend);
++ DEBUG_ON(finfo->fi_bend < finfo->fi_bstart);
++ //DbgFile(file);
++ //DbgDentry(file->f_dentry);
++
++ err = 0;
++#if 0 // todo:
++ if (!au_h_dptr(dentry)->d_inode) {
++ au_update_figen(file);
++ goto out; /* success */
++ }
++#endif
++
++ if (unlikely(au_is_mmapped(file) || d_unhashed(dentry)))
++ goto out_update; /* success */
++
++ again:
++ bstart = ibstart(inode);
++ if (bstart < finfo->fi_bstart
++ && au_flag_test(sb, AuFlag_PLINK)
++ && au_is_plinked(sb, inode)) {
++ struct dentry *parent = dentry->d_parent; // dget_parent()
++ struct inode *dir = parent->d_inode, *h_dir;
++
++ if (test_ro(sb, bstart, inode)) {
++ di_read_lock_parent(parent, !AUFS_I_RLOCK);
++ bstart = err = find_rw_parent_br(dentry, bstart);
++ //bstart = err = find_rw_br(sb, bstart);
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ //todo: err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ di_write_lock_child(dentry);
++ if (bstart != ibstart(inode)) { // todo
++ /* someone changed our inode while we were sleeping */
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ goto again;
++ }
++
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ err = test_and_cpup_dirs(dentry, bstart, NULL);
++
++ // always superio.
++#if 1
++ h_dir = au_h_dptr_i(parent, bstart)->d_inode;
++ hdir_lock(h_dir, dir, bstart);
++ err = sio_cpup_simple(dentry, bstart, -1,
++ au_flags_cpup(CPUP_DTIME, parent));
++ hdir_unlock(h_dir, dir, bstart);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++#else
++ if (!is_au_wkq(current)) {
++ struct cpup_pseudo_link_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bstart,
++ .do_lock = 1
++ };
++ au_wkq_wait(call_cpup_pseudo_link, &args);
++ } else
++ err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
++#endif
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ if (unlikely(err))
++ goto out;
++ }
++
++ err = reopen(file);
++ //err = -1;
++ out_update:
++ if (!err) {
++ au_update_figen(file);
++ //DbgFile(file);
++ return 0; /* success */
++ }
++
++ /* error, close all hidden files */
++ bend = fbend(file);
++ for (bindex = fbstart(file); bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* common function to regular file and dir */
++int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
++ int wlock, int locked)
++{
++ int err, sgen, fgen, pseudo_link;
++ struct dentry *dentry;
++ struct super_block *sb;
++ aufs_bindex_t bstart;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, w %d, l %d\n", DLNPair(dentry), wlock, locked);
++ sb = dentry->d_sb;
++ SiMustAnyLock(sb);
++
++ err = 0;
++ sgen = au_sigen(sb);
++ fi_write_lock(file);
++ fgen = au_figen(file);
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ bstart = dbstart(dentry);
++ pseudo_link = (bstart != ibstart(dentry->d_inode));
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ if (sgen == fgen && !pseudo_link && fbstart(file) == bstart) {
++ if (!wlock)
++ fi_downgrade_lock(file);
++ return 0; /* success */
++ }
++
++ LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
++ if (sgen != au_digen(dentry)) {
++ /*
++ * d_path() and path_lookup() is a simple and good approach
++ * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
++ * deadlock. removed the code.
++ */
++ di_write_lock_child(dentry);
++ err = au_reval_dpath(dentry, sgen);
++ //if (LktrCond) err = -1;
++ di_write_unlock(dentry);
++ if (unlikely(err < 0))
++ goto out;
++ DEBUG_ON(au_digen(dentry) != sgen);
++ }
++
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ err = refresh_file(file, reopen);
++ //if (LktrCond) err = -1;
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ if (!err) {
++ if (!wlock)
++ fi_downgrade_lock(file);
++ } else
++ fi_write_unlock(file);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++// cf. aufs_nopage()
++// for madvise(2)
++static int aufs_readpage(struct file *file, struct page *page)
++{
++ TraceEnter();
++ unlock_page(page);
++ return 0;
++}
++
++// they will never be called.
++#ifdef CONFIG_AUFS_DEBUG
++static int aufs_prepare_write(struct file *file, struct page *page,
++ unsigned from, unsigned to)
++{BUG();return 0;}
++static int aufs_commit_write(struct file *file, struct page *page,
++ unsigned from, unsigned to)
++{BUG();return 0;}
++static int aufs_writepage(struct page *page, struct writeback_control *wbc)
++{BUG();return 0;}
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++static void aufs_sync_page(struct page *page)
++{BUG();}
++#else
++static int aufs_sync_page(struct page *page)
++{BUG(); return 0;}
++#endif
++
++#if 0 // comment
++static int aufs_writepages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{BUG();return 0;}
++static int aufs_readpages(struct file *filp, struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages)
++{BUG();return 0;}
++static sector_t aufs_bmap(struct address_space *mapping, sector_t block)
++{BUG();return 0;}
++#endif
++
++static int aufs_set_page_dirty(struct page *page)
++{BUG();return 0;}
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++static void aufs_invalidatepage (struct page *page, unsigned long offset)
++{BUG();}
++#else
++static int aufs_invalidatepage (struct page *page, unsigned long offset)
++{BUG(); return 0;}
++#endif
++static int aufs_releasepage (struct page *page, gfp_t gfp)
++{BUG();return 0;}
++static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs)
++{BUG();return 0;}
++static struct page* aufs_get_xip_page(struct address_space *mapping,
++ sector_t offset, int create)
++{BUG();return NULL;}
++//static int aufs_migratepage (struct page *newpage, struct page *page)
++//{BUG();return 0;}
++#endif
++
++#if 0 // comment
++struct address_space {
++ struct inode *host; /* owner: inode, block_device */
++ struct radix_tree_root page_tree; /* radix tree of all pages */
++ rwlock_t tree_lock; /* and rwlock protecting it */
++ unsigned int i_mmap_writable;/* count VM_SHARED mappings */
++ struct prio_tree_root i_mmap; /* tree of private and shared mappings */
++ struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
++ spinlock_t i_mmap_lock; /* protect tree, count, list */
++ unsigned int truncate_count; /* Cover race condition with truncate */
++ unsigned long nrpages; /* number of total pages */
++ pgoff_t writeback_index;/* writeback starts here */
++ struct address_space_operations *a_ops; /* methods */
++ unsigned long flags; /* error bits/gfp mask */
++ struct backing_dev_info *backing_dev_info; /* device readahead, etc */
++ spinlock_t private_lock; /* for use by the address_space */
++ struct list_head private_list; /* ditto */
++ struct address_space *assoc_mapping; /* ditto */
++} __attribute__((aligned(sizeof(long))));
++
++struct address_space_operations {
++ int (*writepage)(struct page *page, struct writeback_control *wbc);
++ int (*readpage)(struct file *, struct page *);
++ void (*sync_page)(struct page *);
++
++ /* Write back some dirty pages from this mapping. */
++ int (*writepages)(struct address_space *, struct writeback_control *);
++
++ /* Set a page dirty. Return true if this dirtied it */
++ int (*set_page_dirty)(struct page *page);
++
++ int (*readpages)(struct file *filp, struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages);
++
++ /*
++ * ext3 requires that a successful prepare_write() call be followed
++ * by a commit_write() call - they must be balanced
++ */
++ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
++ int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
++ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
++ sector_t (*bmap)(struct address_space *, sector_t);
++ void (*invalidatepage) (struct page *, unsigned long);
++ int (*releasepage) (struct page *, gfp_t);
++ ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
++ loff_t offset, unsigned long nr_segs);
++ struct page* (*get_xip_page)(struct address_space *, sector_t,
++ int);
++ /* migrate the contents of a page to the specified target */
++ int (*migratepage) (struct page *, struct page *);
++};
++#endif
++
++struct address_space_operations aufs_aop = {
++ .readpage = aufs_readpage,
++#ifdef CONFIG_AUFS_DEBUG
++ .writepage = aufs_writepage,
++ .sync_page = aufs_sync_page,
++ //.writepages = aufs_writepages,
++ .set_page_dirty = aufs_set_page_dirty,
++ //.readpages = aufs_readpages,
++ .prepare_write = aufs_prepare_write,
++ .commit_write = aufs_commit_write,
++ //.bmap = aufs_bmap,
++ .invalidatepage = aufs_invalidatepage,
++ .releasepage = aufs_releasepage,
++ .direct_IO = aufs_direct_IO,
++ .get_xip_page = aufs_get_xip_page,
++ //.migratepage = aufs_migratepage
++#endif
++};
+diff --git a/fs/aufs/file.h b/fs/aufs/file.h
+new file mode 100755
+index 0000000..f0fa448
+--- /dev/null
++++ b/fs/aufs/file.h
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: file.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_FILE_H__
++#define __AUFS_FILE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++// SEEK_xxx are defined in linux/fs.h
++#else
++enum {SEEK_SET, SEEK_CUR, SEEK_END};
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_branch;
++struct aufs_hfile {
++ struct file *hf_file;
++ struct aufs_branch *hf_br;
++};
++
++struct aufs_vdir;
++struct aufs_finfo {
++ atomic_t fi_generation;
++
++ struct aufs_rwsem fi_rwsem;
++ struct aufs_hfile *fi_hfile;
++ aufs_bindex_t fi_bstart, fi_bend;
++
++ union {
++ struct vm_operations_struct *fi_h_vm_ops;
++ struct aufs_vdir *fi_vdir_cache;
++ };
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* file.c */
++extern struct address_space_operations aufs_aop;
++unsigned int au_file_roflags(unsigned int flags);
++struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex,
++ int flags);
++int au_do_open(struct inode *inode, struct file *file,
++ int (*open)(struct file *file, int flags));
++int au_reopen_nondir(struct file *file);
++int au_ready_to_write(struct file *file, loff_t len);
++int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
++ int wlock, int locked);
++
++/* f_op.c */
++extern struct file_operations aufs_file_fop;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++int aufs_flush(struct file *file, fl_owner_t id);
++#else
++int aufs_flush(struct file *file);
++#endif
++
++/* finfo.c */
++struct aufs_finfo *ftofi(struct file *file);
++aufs_bindex_t fbstart(struct file *file);
++aufs_bindex_t fbend(struct file *file);
++struct aufs_vdir *fvdir_cache(struct file *file);
++struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex);
++struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex);
++struct file *au_h_fptr(struct file *file);
++
++void set_fbstart(struct file *file, aufs_bindex_t bindex);
++void set_fbend(struct file *file, aufs_bindex_t bindex);
++void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache);
++void au_hfput(struct aufs_hfile *hf);
++void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *h_file);
++void au_update_figen(struct file *file);
++
++void au_fin_finfo(struct file *file);
++int au_init_finfo(struct file *file);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_figen(struct file *f)
++{
++ return atomic_read(&ftofi(f)->fi_generation);
++}
++
++static inline int au_is_mmapped(struct file *f)
++{
++ return !!(ftofi(f)->fi_h_vm_ops);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * fi_read_lock, fi_write_lock,
++ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
++ */
++SimpleRwsemFuncs(fi, struct file *f, ftofi(f)->fi_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define FiMustReadLock(f) do {\
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustReadLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustWriteLock(f) do { \
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustWriteLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustAnyLock(f) do { \
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustAnyLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustNoWaiters(f) RwMustNoWaiters(&ftofi(f)->fi_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FILE_H__ */
+diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c
+new file mode 100755
+index 0000000..1e09da8
+--- /dev/null
++++ b/fs/aufs/finfo.c
+@@ -0,0 +1,211 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: finfo.c,v 1.23 2007/04/30 05:45:21 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct aufs_finfo *ftofi(struct file *file)
++{
++ struct aufs_finfo *finfo = file->private_data;
++ DEBUG_ON(!finfo
++ || !finfo->fi_hfile
++ || (0 < finfo->fi_bend
++ && (/* stosi(file->f_dentry->d_sb)->si_bend
++ < finfo->fi_bend
++ || */ finfo->fi_bend < finfo->fi_bstart)));
++ return finfo;
++}
++
++// hard/soft set
++aufs_bindex_t fbstart(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_bstart;
++}
++
++aufs_bindex_t fbend(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_bend;
++}
++
++struct aufs_vdir *fvdir_cache(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_vdir_cache;
++}
++
++struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustAnyLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_br && br_count(hf->hf_br) <= 0);
++ return hf->hf_br;
++}
++
++struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustAnyLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_file
++ && file_count(hf->hf_file) <= 0
++ && br_count(hf->hf_br) <= 0);
++ return hf->hf_file;
++}
++
++struct file *au_h_fptr(struct file *file)
++{
++ return au_h_fptr_i(file, fbstart(file));
++}
++
++void set_fbstart(struct file *file, aufs_bindex_t bindex)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex);
++ ftofi(file)->fi_bstart = bindex;
++}
++
++void set_fbend(struct file *file, aufs_bindex_t bindex)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex
++ || bindex < fbstart(file));
++ ftofi(file)->fi_bend = bindex;
++}
++
++void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(!S_ISDIR(file->f_dentry->d_inode->i_mode)
++ || (ftofi(file)->fi_vdir_cache && vdir_cache));
++ ftofi(file)->fi_vdir_cache = vdir_cache;
++}
++
++void au_hfput(struct aufs_hfile *hf)
++{
++ fput(hf->hf_file);
++ hf->hf_file = NULL;
++ DEBUG_ON(!hf->hf_br);
++ br_put(hf->hf_br);
++ hf->hf_br = NULL;
++}
++
++void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustWriteLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ DEBUG_ON(val && file_count(val) <= 0);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(val && hf->hf_file);
++ if (hf->hf_file)
++ au_hfput(hf);
++ if (val) {
++ hf->hf_file = val;
++ hf->hf_br = stobr(file->f_dentry->d_sb, bindex);
++ }
++}
++
++void au_update_figen(struct file *file)
++{
++ atomic_set(&ftofi(file)->fi_generation, au_digen(file->f_dentry));
++}
++
++void au_fin_finfo(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ struct dentry *dentry;
++ aufs_bindex_t bindex, bend;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ SiMustAnyLock(dentry->d_sb);
++
++ fi_write_lock(file);
++ bend = fbend(file);
++ bindex = fbstart(file);
++ if (bindex >= 0)
++ for (; bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++
++ finfo = ftofi(file);
++#ifdef CONFIG_AUFS_DEBUG
++ if (finfo->fi_bstart >= 0) {
++ bend = fbend(file);
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
++ struct aufs_hfile *hf;
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_file || hf->hf_br);
++ }
++ }
++#endif
++
++ kfree(finfo->fi_hfile);
++ fi_write_unlock(file);
++ cache_free_finfo(finfo);
++ //file->private_data = NULL;
++}
++
++int au_init_finfo(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ struct dentry *dentry;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!dentry->d_inode);
++
++ finfo = cache_alloc_finfo();
++ if (finfo) {
++ finfo->fi_hfile = kcalloc(sbend(dentry->d_sb) + 1,
++ sizeof(*finfo->fi_hfile), GFP_KERNEL);
++ if (finfo->fi_hfile) {
++ rw_init_wlock(&finfo->fi_rwsem);
++ finfo->fi_bstart = -1;
++ finfo->fi_bend = -1;
++ atomic_set(&finfo->fi_generation, au_digen(dentry));
++
++ file->private_data = finfo;
++ return 0; /* success */
++ }
++ cache_free_finfo(finfo);
++ }
++
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
+diff --git a/fs/aufs/hinotify.c b/fs/aufs/hinotify.c
+new file mode 100755
+index 0000000..3bad3f7
+--- /dev/null
++++ b/fs/aufs/hinotify.c
+@@ -0,0 +1,536 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: hinotify.c,v 1.19 2007/05/14 03:39:21 sfjro Exp $ */
++
++#include "aufs.h"
++
++static struct inotify_handle *in_handle;
++static const __u32 in_mask = (IN_MOVE | IN_DELETE | IN_CREATE /* | IN_ACCESS */
++ | IN_MODIFY | IN_ATTRIB
++ | IN_DELETE_SELF | IN_MOVE_SELF);
++
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *hidden_inode)
++{
++ int err;
++ struct aufs_hinotify *hin;
++ s32 wd;
++
++ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, hidden_inode->i_ino);
++
++ err = -ENOMEM;
++ hin = cache_alloc_hinotify();
++ if (hin) {
++ DEBUG_ON(hinode->hi_notify);
++ hinode->hi_notify = hin;
++ hin->hin_aufs_inode = inode;
++ inotify_init_watch(&hin->hin_watch);
++ wd = inotify_add_watch(in_handle, &hin->hin_watch, hidden_inode,
++ in_mask);
++ if (wd >= 0)
++ return 0; /* success */
++
++ err = wd;
++ put_inotify_watch(&hin->hin_watch);
++ cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++void do_free_hinotify(struct aufs_hinode *hinode)
++{
++ int err;
++ struct aufs_hinotify *hin;
++
++ TraceEnter();
++
++ hin = hinode->hi_notify;
++ if (hin) {
++ err = 0;
++ if (atomic_read(&hin->hin_watch.count))
++ err = inotify_rm_watch(in_handle, &hin->hin_watch);
++
++ if (!err) {
++ cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ } else
++ IOErr1("failed inotify_rm_watch() %d\n", err);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void ctl_hinotify(struct aufs_hinode *hinode, const __u32 mask)
++{
++ struct inode *hi;
++ struct inotify_watch *watch;
++
++ hi = hinode->hi_inode;
++ LKTRTrace("hi%lu, sb %p, 0x%x\n", hi->i_ino, hi->i_sb, mask);
++ if (0 && !strcmp(current->comm, "link"))
++ dump_stack();
++ IMustLock(hi);
++ if (!hinode->hi_notify)
++ return;
++
++ watch = &hinode->hi_notify->hin_watch;
++#if 0
++ {
++ u32 wd;
++ wd = inotify_find_update_watch(in_handle, hi, mask);
++ TraceErr(wd);
++ // ignore an err;
++ }
++#else
++ watch->mask = mask;
++ smp_mb();
++#endif
++ LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
++}
++
++#define suspend_hinotify(hi) ctl_hinotify(hi, 0)
++#define resume_hinotify(hi) ctl_hinotify(hi, in_mask)
++
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("i%lu, b%d, lsc %d\n", dir->i_ino, bindex, lsc);
++ DEBUG_ON(!S_ISDIR(dir->i_mode));
++ hinode = itoii(dir)->ii_hinode + bindex;
++ DEBUG_ON(h_dir != hinode->hi_inode);
++
++ hi_lock(h_dir, lsc);
++ if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
++ suspend_hinotify(hinode);
++}
++
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("i%lu, b%d\n", dir->i_ino, bindex);
++ DEBUG_ON(!S_ISDIR(dir->i_mode));
++ hinode = itoii(dir)->ii_hinode + bindex;
++ DEBUG_ON(h_dir != hinode->hi_inode);
++
++ if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
++ resume_hinotify(hinode);
++ i_unlock(h_dir);
++}
++
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
++
++ vfsub_lock_rename(h_parents[0], h_parents[1]);
++ hinode = itoii(dirs[0])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
++ suspend_hinotify(hinode);
++ if (issamedir)
++ return;
++ hinode = itoii(dirs[1])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
++ suspend_hinotify(hinode);
++}
++
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
++
++ hinode = itoii(dirs[0])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
++ resume_hinotify(hinode);
++ if (!issamedir) {
++ hinode = itoii(dirs[1])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
++ resume_hinotify(hinode);
++ }
++ vfsub_unlock_rename(h_parents[0], h_parents[1]);
++}
++
++void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ aufs_bindex_t bindex, bend;
++ struct inode *hi;
++
++ LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
++
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); bindex <= bend; bindex++) {
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi) {
++ //hi_lock(hi, AUFS_LSC_H_CHILD);
++ igrab(hi);
++ set_h_iptr(inode, bindex, NULL, 0);
++ set_h_iptr(inode, bindex, igrab(hi), flags);
++ iput(hi);
++ //i_unlock(hi);
++ }
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DEBUG
++static char *in_name(u32 mask)
++{
++#define test_ret(flag) if (mask & flag) return #flag;
++ test_ret(IN_ACCESS);
++ test_ret(IN_MODIFY);
++ test_ret(IN_ATTRIB);
++ test_ret(IN_CLOSE_WRITE);
++ test_ret(IN_CLOSE_NOWRITE);
++ test_ret(IN_OPEN);
++ test_ret(IN_MOVED_FROM);
++ test_ret(IN_MOVED_TO);
++ test_ret(IN_CREATE);
++ test_ret(IN_DELETE);
++ test_ret(IN_DELETE_SELF);
++ test_ret(IN_MOVE_SELF);
++ test_ret(IN_UNMOUNT);
++ test_ret(IN_Q_OVERFLOW);
++ test_ret(IN_IGNORED);
++ return "";
++#undef test_ret
++}
++#else
++#define in_name(m) "??"
++#endif
++
++static int dec_gen_by_name(struct inode *dir, const char *_name, u32 mask)
++{
++ int err;
++ struct dentry *parent, *child;
++ struct inode *inode;
++ struct qstr *dname;
++ char *name = (void*)_name;
++ unsigned int len;
++
++ LKTRTrace("i%lu, %s, 0x%x %s\n",
++ dir->i_ino, name, mask, in_name(mask));
++
++ err = -1;
++ parent = d_find_alias(dir);
++ if (unlikely(!parent))
++ goto out;
++
++#if 0
++ if (unlikely(!memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ name += AUFS_WH_PFX_LEN;
++#endif
++ len = strlen(name);
++ spin_lock(&dcache_lock);
++ list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
++ dname = &child->d_name;
++ if (len == dname->len && !memcmp(dname->name, name, len)) {
++ au_digen_dec(child);
++#if 1
++ //todo: why both are needed
++ if (mask & IN_MOVE) {
++ spin_lock(&child->d_lock);
++ __d_drop(child);
++ spin_unlock(&child->d_lock);
++ }
++#endif
++
++ inode = child->d_inode;
++ if (inode)
++ au_iigen_dec(inode);
++ err = !!inode;
++
++ // todo: the i_nlink of newly created name by link(2)
++ // should be updated
++ // todo: some nfs dentry doesn't notified at deleteing
++ break;
++ }
++ }
++ spin_unlock(&dcache_lock);
++ dput(parent);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct postproc_args {
++ struct inode *h_dir, *dir, *h_child_inode;
++ char *h_child_name;
++ u32 mask;
++};
++
++static void dec_gen_by_ino(struct postproc_args *a)
++{
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend, bfound;
++ struct xino xino;
++ struct inode *cinode;
++
++ TraceEnter();
++
++ sb = a->dir->i_sb;
++ DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++
++ bfound = -1;
++ bend = ibend(a->dir);
++ for (bindex = ibstart(a->dir); bfound == -1 && bindex <= bend; bindex++)
++ if (au_h_iptr_i(a->dir, bindex) == a->h_dir)
++ bfound = bindex;
++ if (bfound < 0)
++ return;
++
++ bindex = find_brindex(sb, itoii(a->dir)->ii_hinode[bfound + 0].hi_id);
++ if (bindex < 0)
++ return;
++ if (unlikely(xino_read(sb, bindex, a->h_child_inode->i_ino, &xino)))
++ return;
++ cinode = NULL;
++ if (xino.ino)
++ cinode = ilookup(sb, xino.ino);
++ if (cinode) {
++#if 1
++ if (1 || a->mask & IN_MOVE) {
++ struct dentry *child;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(child, &cinode->i_dentry, d_alias)
++ au_digen_dec(child);
++ spin_unlock(&dcache_lock);
++ }
++#endif
++ au_iigen_dec(cinode);
++ iput(cinode);
++ }
++}
++
++static void reset_ino(struct postproc_args *a)
++{
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++ struct inode *h_dir;
++
++ sb = a->dir->i_sb;
++ bend = ibend(a->dir);
++ for (bindex = ibstart(a->dir); bindex <= bend; bindex++) {
++ h_dir = au_h_iptr_i(a->dir, bindex);
++ if (h_dir && h_dir != a->h_dir)
++ xino_write0(sb, bindex, h_dir->i_ino);
++ /* ignore this error */
++ }
++}
++
++static void postproc(void *args)
++{
++ struct postproc_args *a = args;
++ struct super_block *sb;
++ struct aufs_vdir *vdir;
++
++ //au_debug_on();
++ LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++ DEBUG_ON(!a->dir);
++#if 0//def ForceInotify
++ Dbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++#endif
++
++ i_lock(a->dir);
++ sb = a->dir->i_sb;
++ si_read_lock(sb); // consider write_lock
++ ii_write_lock_parent(a->dir);
++
++ /* make dir entries obsolete */
++ vdir = ivdir(a->dir);
++ if (vdir)
++ vdir->vd_jiffy = 0;
++ a->dir->i_version++;
++
++ /*
++ * special handling root directory,
++ * sine d_revalidate may not be called later.
++ * main purpose is maintaining i_nlink.
++ */
++ if (unlikely(a->dir->i_ino == AUFS_ROOT_INO))
++ au_cpup_attr_all(a->dir);
++
++ if (a->h_child_inode && au_flag_test(sb, AuFlag_XINO))
++ dec_gen_by_ino(a);
++ else if (a->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
++ reset_ino(a);
++
++ ii_write_unlock(a->dir);
++ si_read_unlock(sb);
++ i_unlock(a->dir);
++
++ au_mntput(a->dir->i_sb);
++ iput(a->h_child_inode);
++ iput(a->h_dir);
++ iput(a->dir);
++#if 0
++ if (atomic_dec_and_test(&stosi(sb)->si_hinotify))
++ wake_up_all(&stosi(sb)->si_hinotify_wq);
++#endif
++ kfree(a);
++ //au_debug_off();
++}
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
++ u32 cookie, const char *h_child_name,
++ struct inode *h_child_inode)
++{
++ struct aufs_hinotify *hinotify;
++ struct postproc_args *args;
++ int len;
++ char *p;
++ struct inode *dir;
++ //static DECLARE_WAIT_QUEUE_HEAD(wq);
++
++ //au_debug_on();
++ LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++ //au_debug_off();
++ //IMustLock(h_dir);
++#if 0 //defined(ForceInotify) || defined(DbgInotify)
++ Dbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++#endif
++ /* if IN_UNMOUNT happens, there must be another bug */
++ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++ put_inotify_watch(watch);
++ return;
++ }
++
++ switch (mask & IN_ALL_EVENTS) {
++ case IN_MODIFY:
++ case IN_ATTRIB:
++ if (h_child_name)
++ return;
++ break;
++
++ case IN_MOVED_FROM:
++ case IN_MOVED_TO:
++ case IN_CREATE:
++ DEBUG_ON(!h_child_name || !h_child_inode);
++ break;
++ case IN_DELETE:
++ /*
++ * aufs never be able to get this child inode.
++ * revalidation should be in d_revalide()
++ * by checking i_nlink, i_generation or d_unhashed().
++ */
++ DEBUG_ON(!h_child_name);
++ break;
++
++ case IN_DELETE_SELF:
++ case IN_MOVE_SELF:
++ DEBUG_ON(h_child_name || h_child_inode);
++ break;
++
++ case IN_ACCESS:
++ default:
++ DEBUG_ON(1);
++ }
++
++#ifdef DbgInotify
++ WARN_ON(1);
++#endif
++
++ /* iput() will be called in postproc() */
++ hinotify = container_of(watch, struct aufs_hinotify, hin_watch);
++ DEBUG_ON(!hinotify || !hinotify->hin_aufs_inode);
++ dir = hinotify->hin_aufs_inode;
++
++ /* force re-lookup in next d_revalidate() */
++ if (dir->i_ino != AUFS_ROOT_INO)
++ au_iigen_dec(dir);
++ len = 0;
++ if (h_child_name && dec_gen_by_name(dir, h_child_name, mask))
++ len = strlen(h_child_name);
++
++ //wait_event(wq, (args = kmalloc(sizeof(*args), GFP_KERNEL)));
++ args = kmalloc(sizeof(*args) + len + 1, GFP_KERNEL);
++ if (unlikely(!args)) {
++ Err("no memory\n");
++ return;
++ }
++ args->mask = mask;
++ args->dir = igrab(dir);
++ args->h_dir = igrab(watch->inode);
++ args->h_child_inode = NULL;
++ if (len) {
++ if (h_child_inode)
++ args->h_child_inode = igrab(h_child_inode);
++ p = (void*)args;
++ args->h_child_name = p + sizeof(*args);
++ memcpy(args->h_child_name, h_child_name, len + 1);
++ }
++ //atomic_inc(&stosi(args->dir->i_sb)->si_hinotify);
++ /* prohibit umount */
++ au_mntget(args->dir->i_sb);
++ au_wkq_nowait(postproc, args, /*dlgt*/0);
++}
++
++#if 0
++void hinotify_flush(struct super_block *sb)
++{
++ atomic_t *p = &stosi(sb)->si_hinotify;
++ wait_event(stosi(sb)->si_hinotify_wq, !atomic_read(p));
++}
++#endif
++
++static void aufs_inotify_destroy(struct inotify_watch *watch)
++{
++ return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++ .handle_event = aufs_inotify,
++ .destroy_watch = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++int __init au_inotify_init(void)
++{
++ in_handle = inotify_init(&aufs_inotify_ops);
++ if (!IS_ERR(in_handle))
++ return 0;
++ TraceErrPtr(in_handle);
++ return PTR_ERR(in_handle);
++}
++
++void au_inotify_fin(void)
++{
++ inotify_destroy(in_handle);
++}
+diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+new file mode 100755
+index 0000000..1cd0453
+--- /dev/null
++++ b/fs/aufs/i_op.c
+@@ -0,0 +1,641 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op.c,v 1.30 2007/04/23 00:55:05 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include <linux/security.h>
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++#ifdef CONFIG_AUFS_DLGT
++struct security_inode_permission_args {
++ int *errp;
++ struct inode *h_inode;
++ int mask;
++ struct nameidata *fake_nd;
++};
++
++static void call_security_inode_permission(void *args)
++{
++ struct security_inode_permission_args *a = args;
++ LKTRTrace("fsuid %d\n", current->fsuid);
++ *a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
++}
++#endif
++
++static int hidden_permission(struct inode *hidden_inode, int mask,
++ struct nameidata *fake_nd, int brperm, int dlgt)
++{
++ int err, submask;
++ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
++
++ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
++ hidden_inode->i_ino, mask, brperm);
++
++ err = -EACCES;
++ if (unlikely(write_mask && IS_IMMUTABLE(hidden_inode)))
++ goto out;
++
++ /* skip hidden fs test in the case of write to ro branch */
++ submask = mask & ~MAY_APPEND;
++ if (unlikely((write_mask && !br_writable(brperm))
++ || !hidden_inode->i_op
++ || !hidden_inode->i_op->permission)) {
++ //LKTRLabel(generic_permission);
++ err = generic_permission(hidden_inode, submask, NULL);
++ } else {
++ //LKTRLabel(h_inode->permission);
++ err = hidden_inode->i_op->permission(hidden_inode, submask,
++ fake_nd);
++ TraceErr(err);
++ }
++
++#if 1
++ if (!err) {
++#ifndef CONFIG_AUFS_DLGT
++ err = security_inode_permission(hidden_inode, mask, fake_nd);
++#else
++ if (!dlgt)
++ err = security_inode_permission(hidden_inode, mask,
++ fake_nd);
++ else {
++ struct security_inode_permission_args args = {
++ .errp = &err,
++ .h_inode = hidden_inode,
++ .mask = mask,
++ .fake_nd = fake_nd
++ };
++ au_wkq_wait(call_security_inode_permission, &args,
++ /*dlgt*/1);
++ }
++#endif
++ }
++#endif
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int silly_lock(struct inode *inode, struct nameidata *nd)
++{
++ int locked = 0;
++ struct super_block *sb = inode->i_sb;
++
++ LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++#else
++ if (!nd || !nd->dentry) {
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++ } else if (nd->dentry->d_inode != inode) {
++ locked = 1;
++ /* lock child first, then parent */
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++ di_read_lock_parent(nd->dentry, 0);
++ } else {
++ locked = 2;
++ aufs_read_lock(nd->dentry, AUFS_I_RLOCK);
++ }
++#endif
++ return locked;
++}
++
++static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
++{
++ struct super_block *sb = inode->i_sb;
++
++ LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++#else
++ switch (locked) {
++ case 0:
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ break;
++ case 1:
++ di_read_unlock(nd->dentry, 0);
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ break;
++ case 2:
++ aufs_read_unlock(nd->dentry, AUFS_I_RLOCK);
++ break;
++ default:
++ BUG();
++ }
++#endif
++}
++
++static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
++{
++ int err, locked, dlgt;
++ aufs_bindex_t bindex, bend;
++ struct inode *hidden_inode;
++ struct super_block *sb;
++ struct nameidata fake_nd, *p;
++ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
++ const int nondir = !S_ISDIR(inode->i_mode);
++
++ LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
++ "nd %p{%p, %p}\n",
++ inode->i_ino, mask, nondir, write_mask,
++ nd, nd ? nd->dentry : NULL, nd ? nd->mnt : NULL);
++
++ sb = inode->i_sb;
++ locked = silly_lock(inode, nd);
++ dlgt = need_dlgt(sb);
++
++ if (nd)
++ fake_nd = *nd;
++ if (/* unlikely */(nondir || write_mask)) {
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode
++ || ((hidden_inode->i_mode & S_IFMT)
++ != (inode->i_mode & S_IFMT)));
++ err = 0;
++ bindex = ibstart(inode);
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ /* actual test will be delegated to LSM */
++ if (IS_ERR(p))
++ DEBUG_ON(PTR_ERR(p) != -ENOENT);
++ else {
++ err = hidden_permission(hidden_inode, mask, p,
++ sbr_perm(sb, bindex), dlgt);
++ fake_dm_release(p);
++ }
++ if (write_mask && !err) {
++ err = find_rw_br(sb, bindex);
++ if (err >= 0)
++ err = 0;
++ }
++ goto out;
++ }
++
++ /* non-write to dir */
++ err = 0;
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); !err && bindex <= bend; bindex++) {
++ hidden_inode = au_h_iptr_i(inode, bindex);
++ if (!hidden_inode)
++ continue;
++ DEBUG_ON(!S_ISDIR(hidden_inode->i_mode));
++
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ /* actual test will be delegated to LSM */
++ if (IS_ERR(p))
++ DEBUG_ON(PTR_ERR(p) != -ENOENT);
++ else {
++ err = hidden_permission(hidden_inode, mask, p,
++ sbr_perm(sb, bindex), dlgt);
++ fake_dm_release(p);
++ }
++ }
++
++ out:
++ silly_unlock(locked, inode, nd);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ struct dentry *ret, *parent;
++ int err, npositive;
++ struct inode *inode;
++
++ LKTRTrace("dir %lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ DEBUG_ON(IS_ROOT(dentry));
++ IMustLock(dir);
++
++ parent = dentry->d_parent; // dget_parent()
++ aufs_read_lock(parent, !AUFS_I_RLOCK);
++ err = au_alloc_dinfo(dentry);
++ //if (LktrCond) err = -1;
++ ret = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ err = npositive = lkup_dentry(dentry, dbstart(parent), /*type*/0);
++ //err = -1;
++ ret = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ inode = NULL;
++ if (npositive) {
++ inode = au_new_inode(dentry);
++ ret = (void*)inode;
++ }
++ if (!IS_ERR(inode)) {
++#if 1
++ /* d_splice_alias() also supports d_add() */
++ ret = d_splice_alias(inode, dentry);
++ if (unlikely(IS_ERR(ret) && inode))
++ ii_write_unlock(inode);
++#else
++ d_add(dentry, inode);
++#endif
++ }
++
++ out_unlock:
++ di_write_unlock(dentry);
++ out:
++ aufs_read_unlock(parent, !AUFS_I_RLOCK);
++ TraceErrPtr(ret);
++ return ret;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * decide the branch and the parent dir where we will create a new entry.
++ * returns new bindex or an error.
++ * copyup the parent dir if needed.
++ */
++int wr_dir(struct dentry *dentry, int add_entry, struct dentry *src_dentry,
++ aufs_bindex_t force_btgt, int do_lock_srcdir)
++{
++ int err;
++ aufs_bindex_t bcpup, bstart, src_bstart;
++ struct dentry *hidden_parent;
++ struct super_block *sb;
++ struct dentry *parent, *src_parent = NULL;
++ struct inode *dir, *src_dir = NULL;
++
++ LKTRTrace("%.*s, add %d, src %p, force %d, lock_srcdir %d\n",
++ DLNPair(dentry), add_entry, src_dentry, force_btgt,
++ do_lock_srcdir);
++
++ sb = dentry->d_sb;
++ parent = dentry->d_parent; // dget_parent()
++ bcpup = bstart = dbstart(dentry);
++ if (force_btgt < 0) {
++ if (src_dentry) {
++ src_bstart = dbstart(src_dentry);
++ if (src_bstart < bstart)
++ bcpup = src_bstart;
++ }
++ if (test_ro(sb, bcpup, dentry->d_inode)) {
++ if (!add_entry)
++ di_read_lock_parent(parent, !AUFS_I_RLOCK);
++ bcpup = err = find_rw_parent_br(dentry, bcpup);
++ //bcpup = err = find_rw_br(sb, bcpup);
++ if (!add_entry)
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ DEBUG_ON(bstart <= force_btgt
++ || test_ro(sb, force_btgt, dentry->d_inode));
++ bcpup = force_btgt;
++ }
++ LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
++
++ err = bcpup;
++ if (bcpup == bstart)
++ goto out; /* success */
++
++ /* copyup the new parent into the branch we process */
++ hidden_parent = au_h_dptr(dentry)->d_parent; // dget_parent()
++ if (src_dentry) {
++ src_parent = src_dentry->d_parent; // dget_parent()
++ src_dir = src_parent->d_inode;
++ if (do_lock_srcdir)
++ di_write_lock_parent2(src_parent);
++ }
++
++ dir = parent->d_inode;
++ if (add_entry) {
++ au_update_dbstart(dentry);
++ IMustLock(dir);
++ DiMustWriteLock(parent);
++ IiMustWriteLock(dir);
++ } else
++ di_write_lock_parent(parent);
++
++ err = 0;
++ if (!au_h_dptr_i(parent, bcpup))
++ err = cpup_dirs(dentry, bcpup, src_parent);
++ //err = -1;
++ if (!err && add_entry) {
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ DEBUG_ON(!hidden_parent || !hidden_parent->d_inode);
++ hi_lock_parent(hidden_parent->d_inode);
++ err = lkup_neg(dentry, bcpup);
++ //err = -1;
++ i_unlock(hidden_parent->d_inode);
++ }
++
++ if (!add_entry)
++ di_write_unlock(parent);
++ if (do_lock_srcdir)
++ di_write_unlock(src_parent);
++ if (!err)
++ err = bcpup; /* success */
++ //err = -EPERM;
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err, isdir;
++ aufs_bindex_t bstart, bcpup;
++ struct inode *hidden_inode, *inode, *dir, *h_dir, *gh_dir, *gdir;
++ struct dentry *hidden_dentry, *parent;
++ unsigned int udba;
++
++ LKTRTrace("%.*s, ia_valid 0x%x\n", DLNPair(dentry), ia->ia_valid);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ bstart = dbstart(dentry);
++ bcpup = err = wr_dir(dentry, /*add*/0, /*src_dentry*/NULL,
++ /*force_btgt*/-1, /*do_lock_srcdir*/0);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++
++ /* crazy udba locks */
++ udba = au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY);
++ parent = NULL;
++ gdir = gh_dir = dir = h_dir = NULL;
++ if ((udba || bstart != bcpup) && !IS_ROOT(dentry)) {
++ parent = dentry->d_parent; // dget_parent()
++ dir = parent->d_inode;
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ h_dir = au_h_iptr_i(dir, bcpup);
++ }
++ if (parent) {
++ if (unlikely(udba && !IS_ROOT(parent))) {
++ gdir = parent->d_parent->d_inode; // dget_parent()
++ ii_read_lock_parent2(gdir);
++ gh_dir = au_h_iptr_i(gdir, bcpup);
++ hgdir_lock(gh_dir, gdir, bcpup);
++ }
++ hdir_lock(h_dir, dir, bcpup);
++ }
++
++ isdir = S_ISDIR(inode->i_mode);
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++#define HiLock(bindex) do {\
++ if (!isdir) \
++ hi_lock_child(hidden_inode); \
++ else \
++ hdir2_lock(hidden_inode, inode, bindex); \
++ } while (0)
++#define HiUnlock(bindex) do {\
++ if (!isdir) \
++ i_unlock(hidden_inode); \
++ else \
++ hdir_unlock(hidden_inode, inode, bindex); \
++ } while (0)
++
++ if (bstart != bcpup) {
++ loff_t size = -1;
++
++ if ((ia->ia_valid & ATTR_SIZE)
++ && ia->ia_size < i_size_read(inode)) {
++ size = ia->ia_size;
++ ia->ia_valid &= ~ATTR_SIZE;
++ }
++ HiLock(bstart);
++ err = sio_cpup_simple(dentry, bcpup, size,
++ au_flags_cpup(CPUP_DTIME, parent));
++ //err = -1;
++ HiUnlock(bstart);
++ if (unlikely(err || !ia->ia_valid))
++ goto out_unlock;
++
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++ }
++
++ HiLock(bcpup);
++ err = vfsub_notify_change(hidden_dentry, ia, need_dlgt(dentry->d_sb));
++ //err = -1;
++ if (!err)
++ au_cpup_attr_changable(inode);
++ HiUnlock(bcpup);
++#undef HiLock
++#undef HiUnlock
++
++ out_unlock:
++ if (parent) {
++ hdir_unlock(h_dir, dir, bcpup);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++ if (unlikely(gdir)) {
++ hdir_unlock(gh_dir, gdir, bcpup);
++ ii_read_unlock(gdir);
++ }
++ out:
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int hidden_readlink(struct dentry *dentry, int bindex,
++ char __user * buf, int bufsiz)
++{
++ struct super_block *sb;
++ struct dentry *hidden_dentry;
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (unlikely(!hidden_dentry->d_inode->i_op
++ || !hidden_dentry->d_inode->i_op->readlink))
++ return -EINVAL;
++
++ sb = dentry->d_sb;
++ if (!test_ro(sb, bindex, dentry->d_inode)) {
++ touch_atime(sbr_mnt(sb, bindex), hidden_dentry);
++ dentry->d_inode->i_atime = hidden_dentry->d_inode->i_atime;
++ }
++ return hidden_dentry->d_inode->i_op->readlink
++ (hidden_dentry, buf, bufsiz);
++}
++
++static int aufs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
++{
++ int err;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), bufsiz);
++
++ aufs_read_lock(dentry, AUFS_I_RLOCK);
++ err = hidden_readlink(dentry, dbstart(dentry), buf, bufsiz);
++ //err = -1;
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ TraceErr(err);
++ return err;
++}
++
++static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ int err;
++ char *buf;
++ mm_segment_t old_fs;
++
++ LKTRTrace("%.*s, nd %.*s\n", DLNPair(dentry), DLNPair(nd->dentry));
++
++ err = -ENOMEM;
++ buf = __getname();
++ //buf = NULL;
++ if (unlikely(!buf))
++ goto out;
++
++ aufs_read_lock(dentry, AUFS_I_RLOCK);
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = hidden_readlink(dentry, dbstart(dentry), (char __user *)buf,
++ PATH_MAX);
++ //err = -1;
++ set_fs(old_fs);
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++
++ if (err >= 0) {
++ buf[err] = 0;
++ /* will be freed by put_link */
++ nd_set_link(nd, buf);
++ return NULL; /* success */
++ }
++ __putname(buf);
++
++ out:
++ path_release(nd);
++ TraceErr(err);
++ return ERR_PTR(err);
++}
++
++static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
++ void *cookie)
++{
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ __putname(nd_get_link(nd));
++}
++
++/* ---------------------------------------------------------------------- */
++#if 0 // comment
++struct inode_operations {
++ int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
++ struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
++ int (*link) (struct dentry *,struct inode *,struct dentry *);
++ int (*unlink) (struct inode *,struct dentry *);
++ int (*symlink) (struct inode *,struct dentry *,const char *);
++ int (*mkdir) (struct inode *,struct dentry *,int);
++ int (*rmdir) (struct inode *,struct dentry *);
++ int (*mknod) (struct inode *,struct dentry *,int,dev_t);
++ int (*rename) (struct inode *, struct dentry *,
++ struct inode *, struct dentry *);
++ int (*readlink) (struct dentry *, char __user *,int);
++ void * (*follow_link) (struct dentry *, struct nameidata *);
++ void (*put_link) (struct dentry *, struct nameidata *, void *);
++ void (*truncate) (struct inode *);
++ int (*permission) (struct inode *, int, struct nameidata *);
++ int (*setattr) (struct dentry *, struct iattr *);
++ int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
++ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
++ ssize_t (*listxattr) (struct dentry *, char *, size_t);
++ int (*removexattr) (struct dentry *, const char *);
++ void (*truncate_range)(struct inode *, loff_t, loff_t);
++};
++#endif
++
++struct inode_operations aufs_symlink_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++ .readlink = aufs_readlink,
++ .follow_link = aufs_follow_link,
++ .put_link = aufs_put_link
++};
++
++//i_op_add.c
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd);
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry);
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++
++//i_op_del.c
++int aufs_unlink(struct inode *dir, struct dentry *dentry);
++int aufs_rmdir(struct inode *dir, struct dentry *dentry);
++
++// i_op_ren.c
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry);
++
++struct inode_operations aufs_dir_iop = {
++ .create = aufs_create,
++ .lookup = aufs_lookup,
++ .link = aufs_link,
++ .unlink = aufs_unlink,
++ .symlink = aufs_symlink,
++ .mkdir = aufs_mkdir,
++ .rmdir = aufs_rmdir,
++ .mknod = aufs_mknod,
++ .rename = aufs_rename,
++
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++#if 0 // xattr
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr
++#endif
++};
++
++struct inode_operations aufs_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++#if 0 // xattr
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr
++#endif
++};
+diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
+new file mode 100755
+index 0000000..977d773
+--- /dev/null
++++ b/fs/aufs/i_op_add.c
+@@ -0,0 +1,621 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_add.c,v 1.37 2007/05/07 03:46:08 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++/*
++ * final procedure of adding a new entry, except link(2).
++ * remove whiteout, instantiate, copyup the parent dir's times and size
++ * and update version.
++ * if it failed, re-create the removed whiteout.
++ */
++static int epilog(struct dentry *wh_dentry, struct dentry *dentry)
++{
++ int err, rerr;
++ aufs_bindex_t bwh;
++ struct inode *inode, *dir;
++ struct dentry *wh;
++ struct lkup_args lkup;
++
++ LKTRTrace("wh %p, %.*s\n", wh_dentry, DLNPair(dentry));
++
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ bwh = -1;
++ if (wh_dentry) {
++ bwh = dbwh(dentry);
++ err = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode,
++ wh_dentry, dentry, lkup.dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ }
++
++ inode = au_new_inode(dentry);
++ //inode = ERR_PTR(-1);
++ if (!IS_ERR(inode)) {
++ d_instantiate(dentry, inode);
++ dir = dentry->d_parent->d_inode;
++ /* or always cpup dir mtime? */
++ if (ibstart(dir) == dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++ return 0; /* success */
++ }
++
++ err = PTR_ERR(inode);
++ if (!wh_dentry)
++ goto out;
++
++ /* revert */
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bwh);
++ wh = simple_create_wh(dentry, bwh, wh_dentry->d_parent, &lkup);
++ //wh = ERR_PTR(-1);
++ rerr = PTR_ERR(wh);
++ if (!IS_ERR(wh)) {
++ dput(wh);
++ goto out;
++ }
++ IOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * initial procedure of adding a new entry.
++ * prepare writable branch and the parent dir, lock it,
++ * lookup whiteout for the new entry.
++ */
++static struct dentry *
++lock_hdir_lkup_wh(struct dentry *dentry, struct dtime *dt,
++ struct dentry *src_dentry, int do_lock_srcdir)
++{
++ struct dentry *wh_dentry, *parent, *hidden_parent;
++ int err;
++ aufs_bindex_t bstart, bcpup;
++ struct inode *dir, *h_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, src %p\n", DLNPair(dentry), src_dentry);
++
++ parent = dentry->d_parent;
++ bstart = dbstart(dentry);
++ bcpup = err = wr_dir(dentry, 1, src_dentry, -1, do_lock_srcdir);
++ //err = -1;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ dir = parent->d_inode;
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ h_dir = hidden_parent->d_inode;
++ hdir_lock(h_dir, dir, bcpup);
++ if (dt)
++ dtime_store(dt, parent, hidden_parent);
++ if (/* bcpup != bstart || */ bcpup != dbwh(dentry))
++ return NULL; /* success */
++
++ lkup.nfsmnt = au_nfsmnt(parent->d_sb, bcpup);
++ lkup.dlgt = need_dlgt(parent->d_sb);
++ wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, &lkup);
++ //wh_dentry = ERR_PTR(-1);
++ if (IS_ERR(wh_dentry))
++ hdir_unlock(h_dir, dir, bcpup);
++
++ out:
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++enum {Mknod, Symlink, Creat};
++struct simple_arg {
++ int type;
++ union {
++ struct {
++ int mode;
++ struct nameidata *nd;
++ } c;
++ struct {
++ const char *symname;
++ } s;
++ struct {
++ int mode;
++ dev_t dev;
++ } m;
++ } u;
++};
++
++static int add_simple(struct inode *dir, struct dentry *dentry,
++ struct simple_arg *arg)
++{
++ int err, dlgt;
++ struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent;
++ struct inode *hidden_dir;
++ struct dtime dt;
++
++ LKTRTrace("type %d, %.*s\n", arg->type, DLNPair(dentry));
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
++ /*do_lock_srcdir*/0);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ dlgt = need_dlgt(dir->i_sb);
++
++#if 1 // partial testing
++ switch (arg->type) {
++ case Creat:
++#if 0
++ if (arg->u.c.nd) {
++ struct nameidata fake_nd;
++ fake_nd = *arg->u.c.nd;
++ fake_nd.dentry = dget(hidden_parent);
++ fake_nd.mnt = sbr_mnt(dentry->d_sb, dbstart(dentry));
++ mntget(fake_nd.mnt);
++ err = vfsub_create(hidden_dir, hidden_dentry,
++ arg->u.c.mode, &fake_nd, dlgt);
++ path_release(&fake_nd);
++ } else
++#endif
++ err = vfsub_create(hidden_dir, hidden_dentry,
++ arg->u.c.mode, NULL, dlgt);
++ break;
++ case Symlink:
++ err = vfsub_symlink(hidden_dir, hidden_dentry,
++ arg->u.s.symname, S_IALLUGO, dlgt);
++ break;
++ case Mknod:
++ err = vfsub_mknod(hidden_dir, hidden_dentry,
++ arg->u.m.mode, arg->u.m.dev, dlgt);
++ break;
++ default:
++ BUG();
++ }
++#else
++ err = -1;
++#endif
++ if (!err)
++ err = epilog(wh_dentry, dentry);
++ //err = -1;
++
++ /* revert */
++ if (unlikely(err && hidden_dentry->d_inode)) {
++ int rerr;
++ rerr = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
++ //rerr = -1;
++ if (rerr) {
++ IOErr("%.*s revert failure(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++ d_drop(dentry);
++ }
++
++ hdir_unlock(hidden_dir, dir, dbstart(dentry));
++ dput(wh_dentry);
++
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++ struct simple_arg arg = {
++ .type = Mknod,
++ .u.m = {.mode = mode, .dev = dev}
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++ struct simple_arg arg = {
++ .type = Symlink,
++ .u.s.symname = symname
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ struct simple_arg arg = {
++ .type = Creat,
++ .u.c = {.mode = mode, .nd = nd}
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct link_arg {
++ aufs_bindex_t bdst, bsrc;
++ int issamedir, dlgt;
++ struct dentry *src_parent, *parent, *hidden_dentry;
++ struct inode *hidden_dir, *inode;
++};
++
++static int cpup_before_link(struct dentry *src_dentry, struct inode *dir,
++ struct link_arg *a)
++{
++ int err;
++ unsigned int flags;
++ struct inode *hi, *hdir = NULL, *src_dir;
++
++ TraceEnter();
++
++ err = 0;
++ flags = au_flags_cpup(CPUP_DTIME, a->parent);
++ src_dir = a->src_parent->d_inode;
++ if (!a->issamedir) {
++ // todo: dead lock?
++ di_read_lock_parent2(a->src_parent, AUFS_I_RLOCK);
++ // this temporary unlock/lock is safe
++ hdir_unlock(a->hidden_dir, dir, a->bdst);
++ err = test_and_cpup_dirs(src_dentry, a->bdst, a->parent);
++ //err = -1;
++ if (!err) {
++ hdir = au_h_iptr_i(src_dir, a->bdst);
++ hdir_lock(hdir, src_dir, a->bdst);
++ flags = au_flags_cpup(CPUP_DTIME, a->src_parent);
++ }
++ }
++
++ if (!err) {
++ hi = au_h_dptr(src_dentry)->d_inode;
++ hi_lock_child(hi);
++ err = sio_cpup_simple(src_dentry, a->bdst, -1, flags);
++ //err = -1;
++ i_unlock(hi);
++ }
++
++ if (!a->issamedir) {
++ if (hdir)
++ hdir_unlock(hdir, src_dir, a->bdst);
++ hdir_lock(a->hidden_dir, dir, a->bdst);
++ di_read_unlock(a->src_parent, AUFS_I_RLOCK);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int cpup_or_link(struct dentry *src_dentry, struct link_arg *a)
++{
++ int err;
++ struct inode *inode, *h_inode, *h_dst_inode;
++ struct dentry *h_dentry;
++ aufs_bindex_t bstart;
++ struct super_block *sb;
++
++ TraceEnter();
++
++ sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ h_dentry = au_h_dptr(src_dentry);
++ h_inode = h_dentry->d_inode;
++ bstart = ibstart(inode);
++ h_dst_inode = NULL;
++ if (bstart <= a->bdst)
++ h_dst_inode = au_h_iptr_i(inode, a->bdst);
++
++ if (!h_dst_inode) {
++ /* copyup src_dentry as the name of dentry. */
++ set_dbstart(src_dentry, a->bdst);
++ set_h_dptr(src_dentry, a->bdst, dget(a->hidden_dentry));
++ hi_lock_child(h_inode);
++ err = sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
++ au_flags_cpup(!CPUP_DTIME, a->parent));
++ //err = -1;
++ i_unlock(h_inode);
++ set_h_dptr(src_dentry, a->bdst, NULL);
++ set_dbstart(src_dentry, a->bsrc);
++ } else {
++ /* the inode of src_dentry already exists on a.bdst branch */
++ h_dentry = d_find_alias(h_dst_inode);
++ if (h_dentry) {
++ err = vfsub_link(h_dentry, a->hidden_dir,
++ a->hidden_dentry, a->dlgt);
++ dput(h_dentry);
++ } else {
++ IOErr("no dentry found for i%lu on b%d\n",
++ h_dst_inode->i_ino, a->bdst);
++ err = -EIO;
++ }
++ }
++
++ if (!err)
++ append_plink(sb, a->inode, a->hidden_dentry, a->bdst);
++
++ TraceErr(err);
++ return err;
++}
++
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err, rerr;
++ struct dentry *hidden_parent, *wh_dentry, *hidden_src_dentry;
++ struct dtime dt;
++ struct link_arg a;
++ struct super_block *sb;
++
++ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
++ DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ IMustLock(src_dentry->d_inode);
++
++ aufs_read_and_write_lock2(dentry, src_dentry, /*isdir*/0);
++ a.src_parent = src_dentry->d_parent;
++ a.parent = dentry->d_parent;
++ a.issamedir = (a.src_parent == a.parent);
++ di_write_lock_parent(a.parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, !a.issamedir);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ a.inode = src_dentry->d_inode;
++ a.hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = a.hidden_dentry->d_parent;
++ a.hidden_dir = hidden_parent->d_inode;
++ IMustLock(a.hidden_dir);
++
++ err = 0;
++ sb = dentry->d_sb;
++ a.dlgt = need_dlgt(sb);
++
++ //todo: minor optimize, their sb may be same while their bindex differs.
++ a.bsrc = dbstart(src_dentry);
++ a.bdst = dbstart(dentry);
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
++ /*
++ * copyup src_dentry to the branch we process,
++ * and then link(2) to it.
++ * gave up 'pseudo link by cpup' approach,
++ * since nlink may be one and some applications will not work.
++ */
++ if (a.bdst < a.bsrc
++ /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
++ err = cpup_before_link(src_dentry, dir, &a);
++ if (!err) {
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ err = vfsub_link(hidden_src_dentry, a.hidden_dir,
++ a.hidden_dentry, a.dlgt);
++ //err = -1;
++ }
++ } else {
++ if (a.bdst < a.bsrc
++ /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
++ err = cpup_or_link(src_dentry, &a);
++ else {
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ err = vfsub_link(hidden_src_dentry, a.hidden_dir,
++ a.hidden_dentry, a.dlgt);
++ //err = -1;
++ }
++ }
++ if (unlikely(err))
++ goto out_unlock;
++ if (wh_dentry) {
++ err = au_unlink_wh_dentry(a.hidden_dir, wh_dentry, dentry,
++ a.dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_revert;
++ }
++
++ dir->i_version++;
++ if (ibstart(dir) == dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ if (!d_unhashed(a.hidden_dentry)
++ /* || hidden_old_inode->i_nlink <= nlink */
++ /* || SB_NFS(hidden_src_dentry->d_sb) */) {
++ dentry->d_inode = igrab(a.inode);
++ d_instantiate(dentry, a.inode);
++ a.inode->i_nlink++;
++ a.inode->i_ctime = dir->i_ctime;
++ } else
++ /* nfs case (< 2.6.15) */
++ d_drop(dentry);
++#if 0
++ au_debug_on();
++ DbgInode(a.inode);
++ au_debug_off();
++ {
++ aufs_bindex_t i;
++ for (i = ibstart(a.inode); i <= ibend(a.inode); i++) {
++ struct xino xino;
++ struct inode *hi;
++ hi = au_h_iptr_i(a.inode, i);
++ if (hi) {
++ xino_read(sb, i, hi->i_ino, &xino);
++ Dbg("hi%lu, i%lu\n", hi->i_ino, xino.ino);
++ }
++ }
++ }
++#endif
++ goto out_unlock; /* success */
++
++ out_revert:
++#if 0 // remove
++ if (d_unhashed(a.hidden_dentry)) {
++ /* hardlink on nfs (< 2.6.15) */
++ struct dentry *d;
++ const struct qstr *name = &a.hidden_dentry->d_name;
++ DEBUG_ON(a.hidden_dentry->d_parent->d_inode != a.hidden_dir);
++ // do not superio.
++ d = lkup_one(name->name, a.hidden_dentry->d_parent, name->len,
++ au_nfsmnt(sb, a.bdst)??, need_dlgt(sb));
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out_rerr;
++ dput(a.hidden_dentry);
++ a.hidden_dentry = d;
++ DEBUG_ON(!d->d_inode);
++ }
++#endif
++ rerr = vfsub_unlink(a.hidden_dir, a.hidden_dentry, a.dlgt);
++ //rerr = -1;
++ if (!rerr)
++ goto out_dt;
++// out_rerr:
++ IOErr("%.*s reverting failed(%d, %d)\n", DLNPair(dentry), err, rerr);
++ err = -EIO;
++ out_dt:
++ d_drop(dentry);
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++ out_unlock:
++ hdir_unlock(a.hidden_dir, dir, a.bdst);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(a.parent);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err, rerr, diropq, dlgt;
++ struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent,
++ *opq_dentry;
++ struct inode *hidden_dir, *hidden_inode;
++ struct dtime dt;
++ aufs_bindex_t bindex;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s, mode 0%o\n", dir->i_ino, DLNPair(dentry), mode);
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
++ /*do_lock_srcdir*/0);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dentry->d_sb;
++ bindex = dbstart(dentry);
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ dlgt = need_dlgt(sb);
++
++ err = vfsub_mkdir(hidden_dir, hidden_dentry, mode, dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ hidden_inode = hidden_dentry->d_inode;
++
++ /* make the dir opaque */
++ diropq = 0;
++ if (unlikely(wh_dentry || au_flag_test(sb, AuFlag_ALWAYS_DIROPQ))) {
++ hi_lock_child(hidden_inode);
++ opq_dentry = create_diropq(dentry, bindex, dlgt);
++ //opq_dentry = ERR_PTR(-1);
++ i_unlock(hidden_inode);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out_dir;
++ dput(opq_dentry);
++ diropq = 1;
++ }
++
++ err = epilog(wh_dentry, dentry);
++ //err = -1;
++ if (!err) {
++ dir->i_nlink++;
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (unlikely(diropq)) {
++ LKTRLabel(revert opq);
++ hi_lock_child(hidden_inode);
++ rerr = remove_diropq(dentry, bindex, dlgt);
++ //rerr = -1;
++ i_unlock(hidden_inode);
++ if (rerr) {
++ IOErr("%.*s reverting diropq failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ }
++
++ out_dir:
++ LKTRLabel(revert dir);
++ rerr = vfsub_rmdir(hidden_dir, hidden_dentry, dlgt);
++ //rerr = -1;
++ if (rerr) {
++ IOErr("%.*s reverting dir failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ d_drop(dentry);
++ dtime_revert(&dt, /*fake flag*/CPUP_LOCKED_GHDIR);
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
+new file mode 100755
+index 0000000..f29b204
+--- /dev/null
++++ b/fs/aufs/i_op_del.c
+@@ -0,0 +1,414 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_del.c,v 1.35 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++/* returns,
++ * 0: wh is unnecessary
++ * plus: wh is necessary
++ * minus: error
++ */
++int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dentry *locked)
++{
++ int need_wh, err;
++ aufs_bindex_t bstart;
++ struct dentry *hidden_dentry;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
++ DLNPair(dentry), isdir, *bcpup, locked);
++ sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
++ hidden_dentry = au_h_dptr(dentry);
++ if (*bcpup < 0) {
++ *bcpup = bstart;
++ if (test_ro(sb, bstart, dentry->d_inode)) {
++ *bcpup = err = find_rw_parent_br(dentry, bstart);
++ //*bcpup = err = find_rw_br(sb, bstart);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ /* braces are added to stop a warning */
++ DEBUG_ON(bstart < *bcpup
++ || test_ro(sb, *bcpup, dentry->d_inode));
++ }
++ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
++
++ if (*bcpup != bstart) {
++ err = cpup_dirs(dentry, *bcpup, locked);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ need_wh = 1;
++ } else {
++ //struct nameidata nd;
++ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
++ old_bend = dbend(dentry);
++ if (isdir) {
++ bdiropq = dbdiropq(dentry);
++ set_dbdiropq(dentry, -1);
++ }
++ err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0);
++ //err = -1;
++ if (isdir)
++ set_dbdiropq(dentry, bdiropq);
++ if (unlikely(err < 0))
++ goto out;
++ new_bend = dbend(dentry);
++ if (!need_wh && old_bend != new_bend) {
++ set_h_dptr(dentry, new_bend, NULL);
++ set_dbend(dentry, old_bend);
++#if 0
++ } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) {
++ LKTRTrace("negative\n");
++ set_h_dptr(dentry, new_bend, NULL);
++ set_dbend(dentry, old_bend);
++ need_wh = 0;
++#endif
++ }
++ }
++ LKTRTrace("need_wh %d\n", need_wh);
++ err = need_wh;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static struct dentry *
++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dtime *dt)
++{
++ struct dentry *wh_dentry;
++ int err, need_wh;
++ struct dentry *hidden_parent, *parent;
++ struct inode *dir, *h_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
++
++ err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
++ //err = -1;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ hidden_parent = au_h_dptr_i(parent, *bcpup);
++ h_dir = hidden_parent->d_inode;
++ hdir_lock(h_dir, dir, *bcpup);
++ dtime_store(dt, parent, hidden_parent);
++ if (!need_wh)
++ return NULL; /* success, no need to create whiteout */
++
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
++ //wh_dentry = ERR_PTR(-1);
++ if (!IS_ERR(wh_dentry))
++ goto out; /* success */
++ /* returns with the parent is locked and wh_dentry is DGETed */
++
++ hdir_unlock(h_dir, dir, *bcpup);
++
++ out:
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
++ struct aufs_nhash *whlist, struct inode *dir)
++{
++ int rmdir_later, err;
++ struct dentry *hidden_dentry;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++
++ err = rename_whtmp(dentry, bindex);
++ //err = -1;
++#if 0
++ //todo: bug
++ if (unlikely(err)) {
++ au_direval_inc(dentry->d_parent);
++ return err;
++ }
++#endif
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!au_is_nfs(hidden_dentry->d_sb)) {
++ const int dirwh = stosi(dentry->d_sb)->si_dirwh;
++ rmdir_later = (dirwh <= 1);
++ if (!rmdir_later)
++ rmdir_later = is_longer_wh(whlist, bindex, dirwh);
++ if (rmdir_later)
++ return rmdir_later;
++ }
++
++ err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
++ //err = -1;
++ if (unlikely(err)) {
++ IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
++ DLNPair(hidden_dentry), bindex, err);
++ err = 0;
++ }
++ TraceErr(err);
++ return err;
++}
++
++static void epilog(struct inode *dir, struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ d_drop(dentry);
++ dentry->d_inode->i_ctime = dir->i_ctime;
++ if (atomic_read(&dentry->d_count) == 1) {
++ set_h_dptr(dentry, dbstart(dentry), NULL);
++ au_update_dbstart(dentry);
++ }
++ if (ibstart(dir) == bindex)
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++}
++
++static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
++ aufs_bindex_t bwh, struct dtime *dt, int dlgt)
++{
++ int rerr;
++
++ rerr = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode, wh_dentry,
++ dentry, dlgt);
++ //rerr = -1;
++ if (!rerr) {
++ set_dbwh(dentry, bwh);
++ dtime_revert(dt, !CPUP_LOCKED_GHDIR);
++ return 0;
++ }
++
++ IOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err, dlgt;
++ struct inode *inode, *hidden_dir;
++ struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
++ struct dtime dt;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; // possible?
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++
++ bstart = dbstart(dentry);
++ bwh = dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dir->i_sb;
++ dlgt = need_dlgt(sb);
++ hidden_dentry = au_h_dptr(dentry);
++ dget(hidden_dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++
++ if (bindex == bstart) {
++ err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
++ //err = -1;
++ } else {
++ DEBUG_ON(!wh_dentry);
++ hidden_parent = wh_dentry->d_parent;
++ DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ err = 0;
++ }
++
++ if (!err) {
++ inode->i_nlink--;
++ epilog(dir, dentry, bindex);
++#if 0
++ xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
++ /* ignore this error */
++#endif
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (wh_dentry) {
++ int rerr;
++ rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ dput(hidden_dentry);
++ out:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err, rmdir_later;
++ struct inode *inode, *hidden_dir;
++ struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
++ struct dtime dt;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct rmdir_whtmp_arg *arg;
++ struct aufs_nhash *whlist;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; // possible?
++ IMustLock(inode);
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++
++ err = -ENOMEM;
++ arg = kmalloc(sizeof(*arg), GFP_KERNEL);
++ //arg = NULL;
++ if (unlikely(!arg))
++ goto out_whlist;
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ err = test_empty(dentry, whlist);
++ //err = -1;
++ if (unlikely(err))
++ goto out_arg;
++
++ bstart = dbstart(dentry);
++ bwh = dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_arg;
++
++ hidden_dentry = au_h_dptr(dentry);
++ dget(hidden_dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++
++ rmdir_later = 0;
++ if (bindex == bstart) {
++ IMustLock(hidden_dir);
++ err = renwh_and_rmdir(dentry, bstart, whlist, dir);
++ //err = -1;
++ if (err > 0) {
++ rmdir_later = err;
++ err = 0;
++ }
++ } else {
++ DEBUG_ON(!wh_dentry);
++ hidden_parent = wh_dentry->d_parent;
++ DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ err = 0;
++ }
++
++ sb = dentry->d_sb;
++ if (!err) {
++ //aufs_bindex_t bi, bend;
++
++ au_reset_hinotify(inode, /*flags*/0);
++ inode->i_nlink = 0;
++ set_dbdiropq(dentry, -1);
++ epilog(dir, dentry, bindex);
++
++ if (rmdir_later) {
++ kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
++ inode, arg);
++ arg = NULL;
++ }
++
++#if 0
++ bend = dbend(dentry);
++ for (bi = bstart; bi <= bend; bi++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(dentry, bi);
++ if (hd && hd->d_inode)
++ xino_write0(sb, bi, hd->d_inode->i_ino);
++ /* ignore this error */
++ }
++#endif
++
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ LKTRLabel(revert);
++ if (wh_dentry) {
++ int rerr;
++ rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
++ need_dlgt(sb));
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ dput(hidden_dentry);
++ out_arg:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ kfree(arg);
++ out_whlist:
++ nhash_del(whlist);
++ out:
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
+new file mode 100755
+index 0000000..08137f9
+--- /dev/null
++++ b/fs/aufs/i_op_ren.c
+@@ -0,0 +1,637 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_ren.c,v 1.39 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++enum {SRC, DST};
++struct rename_args {
++ struct dentry *hidden_dentry[2], *parent[2], *hidden_parent[2];
++ struct aufs_nhash whlist;
++ aufs_bindex_t btgt, bstart[2];
++ struct super_block *sb;
++
++ unsigned int isdir:1;
++ unsigned int issamedir:1;
++ unsigned int whsrc:1;
++ unsigned int whdst:1;
++ unsigned int dlgt:1;
++} __attribute__((aligned(sizeof(long))));
++
++static int do_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry,
++ struct rename_args *a)
++{
++ int err, need_diropq, bycpup, rerr;
++ struct rmdir_whtmp_arg *tharg;
++ struct dentry *wh_dentry[2], *hidden_dst, *hg_parent;
++ struct inode *hidden_dir[2];
++ aufs_bindex_t bindex, bend;
++ unsigned int flags;
++ struct lkup_args lkup = {.dlgt = a->dlgt};
++
++ LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
++ "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
++ "flags{%d, %d, %d, %d}\n",
++ DLNPair(a->parent[SRC]), DLNPair(src_dentry),
++ DLNPair(a->parent[DST]), DLNPair(dentry),
++ a->hidden_dentry[SRC], a->hidden_dentry[DST],
++ a->hidden_parent[SRC], a->hidden_parent[DST],
++ &a->whlist, a->btgt,
++ a->bstart[SRC], a->bstart[DST],
++ a->isdir, a->issamedir, a->whsrc, a->whdst);
++ hidden_dir[SRC] = a->hidden_parent[SRC]->d_inode;
++ hidden_dir[DST] = a->hidden_parent[DST]->d_inode;
++ IMustLock(hidden_dir[SRC]);
++ IMustLock(hidden_dir[DST]);
++
++ /* prepare workqueue arg */
++ hidden_dst = NULL;
++ tharg = NULL;
++ if (a->isdir && a->hidden_dentry[DST]->d_inode) {
++ err = -ENOMEM;
++ tharg = kmalloc(sizeof(*tharg), GFP_KERNEL);
++ //tharg = NULL;
++ if (unlikely(!tharg))
++ goto out;
++ hidden_dst = dget(a->hidden_dentry[DST]);
++ }
++
++ wh_dentry[SRC] = wh_dentry[DST] = NULL;
++ lkup.nfsmnt = au_nfsmnt(a->sb, a->btgt);
++ /* create whiteout for src_dentry */
++ if (a->whsrc) {
++ wh_dentry[SRC] = simple_create_wh(src_dentry, a->btgt,
++ a->hidden_parent[SRC], &lkup);
++ //wh_dentry[SRC] = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry[SRC]);
++ if (IS_ERR(wh_dentry[SRC]))
++ goto out_tharg;
++ }
++
++ /* lookup whiteout for dentry */
++ if (a->whdst) {
++ struct dentry *d;
++ d = lkup_wh(a->hidden_parent[DST], &dentry->d_name, &lkup);
++ //d = ERR_PTR(-1);
++ err = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out_whsrc;
++ if (!d->d_inode)
++ dput(d);
++ else
++ wh_dentry[DST] = d;
++ }
++
++ /* rename dentry to tmpwh */
++ if (tharg) {
++ err = rename_whtmp(dentry, a->btgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_whdst;
++ set_h_dptr(dentry, a->btgt, NULL);
++ err = lkup_neg(dentry, a->btgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_whtmp;
++ a->hidden_dentry[DST] = au_h_dptr_i(dentry, a->btgt);
++ }
++
++ /* cpup src */
++ if (a->hidden_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
++ flags = au_flags_cpup(!CPUP_DTIME, a->parent[SRC]);
++ hg_parent = a->hidden_parent[SRC]->d_parent;
++ if (!(flags & CPUP_LOCKED_GHDIR)
++ && hg_parent == a->hidden_parent[DST])
++ flags |= CPUP_LOCKED_GHDIR;
++
++ hi_lock_child(a->hidden_dentry[SRC]->d_inode);
++ err = sio_cpup_simple(src_dentry, a->btgt, -1, flags);
++ //err = -1; // untested dir
++ i_unlock(a->hidden_dentry[SRC]->d_inode);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++
++#if 0
++ /* clear the target ino in xino */
++ LKTRTrace("dir %d, dst inode %p\n", a->isdir, a->hidden_dentry[DST]->d_inode);
++ if (a->isdir && a->hidden_dentry[DST]->d_inode) {
++ Dbg("here\n");
++ err = xino_write(a->sb, a->btgt,
++ a->hidden_dentry[DST]->d_inode->i_ino, 0);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++#endif
++
++ /* rename by vfs_rename or cpup */
++ need_diropq = a->isdir
++ && (wh_dentry[DST]
++ || dbdiropq(dentry) == a->btgt
++ || au_flag_test(a->sb, AuFlag_ALWAYS_DIROPQ));
++ bycpup = 0;
++ if (dbstart(src_dentry) == a->btgt) {
++ if (need_diropq && dbdiropq(src_dentry) == a->btgt)
++ need_diropq = 0;
++ err = vfsub_rename(hidden_dir[SRC], au_h_dptr(src_dentry),
++ hidden_dir[DST], a->hidden_dentry[DST],
++ a->dlgt);
++ //err = -1;
++ } else {
++ bycpup = 1;
++ flags = au_flags_cpup(!CPUP_DTIME, a->parent[DST]);
++ hg_parent = a->hidden_parent[DST]->d_parent;
++ if (!(flags & CPUP_LOCKED_GHDIR)
++ && hg_parent == a->hidden_parent[SRC])
++ flags |= CPUP_LOCKED_GHDIR;
++
++ hi_lock_child(a->hidden_dentry[SRC]->d_inode);
++ set_dbstart(src_dentry, a->btgt);
++ set_h_dptr(src_dentry, a->btgt, dget(a->hidden_dentry[DST]));
++ //DbgDentry(src_dentry);
++ //DbgInode(src_dentry->d_inode);
++ err = sio_cpup_single(src_dentry, a->btgt, a->bstart[SRC], -1,
++ flags);
++ //err = -1; // untested dir
++ if (unlikely(err)) {
++ set_h_dptr(src_dentry, a->btgt, NULL);
++ set_dbstart(src_dentry, a->bstart[SRC]);
++ }
++ i_unlock(a->hidden_dentry[SRC]->d_inode);
++ }
++ if (unlikely(err))
++ goto out_whtmp;
++
++ /* make dir opaque */
++ if (need_diropq) {
++ struct dentry *diropq;
++ struct inode *h_inode;
++
++ h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
++ hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
++ diropq = create_diropq(src_dentry, a->btgt, a->dlgt);
++ //diropq = ERR_PTR(-1);
++ hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
++ err = PTR_ERR(diropq);
++ if (IS_ERR(diropq))
++ goto out_rename;
++ dput(diropq);
++ }
++
++ /* remove whiteout for dentry */
++ if (wh_dentry[DST]) {
++ err = au_unlink_wh_dentry(hidden_dir[DST], wh_dentry[DST],
++ dentry, a->dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_diropq;
++ }
++
++ /* remove whtmp */
++ if (tharg) {
++ if (au_is_nfs(hidden_dst->d_sb)
++ || !is_longer_wh(&a->whlist, a->btgt,
++ stosi(a->sb)->si_dirwh)) {
++ err = rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
++ dentry->d_inode);
++ if (unlikely(err))
++ Warn("failed removing whtmp dir %.*s (%d), "
++ "ignored.\n", DLNPair(hidden_dst), err);
++ } else {
++ kick_rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
++ dentry->d_inode, tharg);
++ dput(hidden_dst);
++ tharg = NULL;
++ }
++ }
++ err = 0;
++ goto out_success;
++
++#define RevertFailure(fmt, args...) do { \
++ IOErrWhck("revert failure: " fmt " (%d, %d)\n", \
++ ##args, err, rerr); \
++ err = -EIO; \
++ } while(0)
++
++ out_diropq:
++ if (need_diropq) {
++ struct inode *h_inode;
++
++ h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
++ // i_lock simplly since inotify is not set to h_inode.
++ hi_lock_parent(h_inode);
++ //hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
++ rerr = remove_diropq(src_dentry, a->btgt, a->dlgt);
++ //rerr = -1;
++ //hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
++ i_unlock(h_inode);
++ if (rerr)
++ RevertFailure("remove diropq %.*s",
++ DLNPair(src_dentry));
++ }
++ out_rename:
++ if (!bycpup) {
++ struct dentry *d;
++ struct qstr *name = &src_dentry->d_name;
++ d = lkup_one(name->name, a->hidden_parent[SRC], name->len,
++ &lkup);
++ //d = ERR_PTR(-1);
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d)) {
++ RevertFailure("lkup_one %.*s", DLNPair(src_dentry));
++ goto out_whtmp;
++ }
++ DEBUG_ON(d->d_inode);
++ rerr = vfsub_rename
++ (hidden_dir[DST], au_h_dptr_i(src_dentry, a->btgt),
++ hidden_dir[SRC], d, a->dlgt);
++ //rerr = -1;
++ d_drop(d);
++ dput(d);
++ //set_h_dptr(src_dentry, a->btgt, NULL);
++ if (rerr)
++ RevertFailure("rename %.*s", DLNPair(src_dentry));
++ } else {
++ rerr = vfsub_unlink(hidden_dir[DST], a->hidden_dentry[DST],
++ a->dlgt);
++ //rerr = -1;
++ set_h_dptr(src_dentry, a->btgt, NULL);
++ set_dbstart(src_dentry, a->bstart[SRC]);
++ if (rerr)
++ RevertFailure("unlink %.*s",
++ DLNPair(a->hidden_dentry[DST]));
++ }
++ out_whtmp:
++ if (tharg) {
++ struct dentry *d;
++ struct qstr *name = &dentry->d_name;
++ LKTRLabel(here);
++ d = lkup_one(name->name, a->hidden_parent[DST], name->len,
++ &lkup);
++ //d = ERR_PTR(-1);
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d)) {
++ RevertFailure("lookup %.*s", LNPair(name));
++ goto out_whdst;
++ }
++ if (d->d_inode) {
++ d_drop(d);
++ dput(d);
++ goto out_whdst;
++ }
++ DEBUG_ON(d->d_inode);
++ rerr = vfsub_rename(hidden_dir[DST], hidden_dst,
++ hidden_dir[DST], d, a->dlgt);
++ //rerr = -1;
++ d_drop(d);
++ dput(d);
++ if (rerr) {
++ RevertFailure("rename %.*s", DLNPair(hidden_dst));
++ goto out_whdst;
++ }
++ set_h_dptr(dentry, a->btgt, NULL);
++ set_h_dptr(dentry, a->btgt, dget(hidden_dst));
++ }
++ out_whdst:
++ dput(wh_dentry[DST]);
++ wh_dentry[DST] = NULL;
++ out_whsrc:
++ if (wh_dentry[SRC]) {
++ LKTRLabel(here);
++ rerr = au_unlink_wh_dentry(hidden_dir[SRC], wh_dentry[SRC],
++ src_dentry, a->dlgt);
++ //rerr = -1;
++ if (rerr)
++ RevertFailure("unlink %.*s", DLNPair(wh_dentry[SRC]));
++ }
++#undef RevertFailure
++ d_drop(src_dentry);
++ bend = dbend(src_dentry);
++ for (bindex = dbstart(src_dentry); bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(src_dentry, bindex);
++ if (hd)
++ d_drop(hd);
++ }
++ d_drop(dentry);
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(dentry, bindex);
++ if (hd)
++ d_drop(hd);
++ }
++ au_update_dbstart(dentry);
++ if (tharg)
++ d_drop(hidden_dst);
++ out_success:
++ dput(wh_dentry[SRC]);
++ dput(wh_dentry[DST]);
++ out_tharg:
++ if (tharg) {
++ dput(hidden_dst);
++ kfree(tharg);
++ }
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * test if @dentry dir can be rename destination or not.
++ * success means, it is a logically empty dir.
++ */
++static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
++ struct aufs_nhash *whlist)
++{
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ return test_empty(dentry, whlist);
++}
++
++/*
++ * test if @dentry dir can be rename source or not.
++ * if it can, return 0 and @children is filled.
++ * success means,
++ * - or, it is a logically empty dir.
++ * - or, it exists on writable branch and has no children including whiteouts
++ * on the lower branch.
++ */
++static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ int err;
++ aufs_bindex_t bstart;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ bstart = dbstart(dentry);
++ if (bstart != btgt) {
++ struct aufs_nhash *whlist;
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++ err = test_empty(dentry, whlist);
++ nhash_del(whlist);
++ goto out;
++ }
++
++ if (bstart == dbtaildir(dentry))
++ return 0; /* success */
++
++ err = au_test_empty_lower(dentry);
++
++ out:
++ if (/* unlikely */(err == -ENOTEMPTY))
++ err = -EXDEV;
++ TraceErr(err);
++ return err;
++}
++
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry)
++{
++ int err, do_dt_dstdir;
++ aufs_bindex_t bend, bindex;
++ struct inode *inode, *dirs[2];
++ enum {PARENT, CHILD};
++ /* reduce stack space */
++ struct {
++ struct rename_args a;
++ struct dtime dt[2][2];
++ } *p;
++
++ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
++ src_dir->i_ino, DLNPair(src_dentry),
++ dir->i_ino, DLNPair(dentry));
++ IMustLock(src_dir);
++ IMustLock(dir);
++ /* braces are added to stop a warning */
++ if (dentry->d_inode) {
++ IMustLock(dentry->d_inode);
++ }
++
++ err = -ENOMEM;
++ BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
++ p = kmalloc(sizeof(*p), GFP_KERNEL);
++ if (unlikely(!p))
++ goto out;
++
++ err = -ENOTDIR;
++ p->a.sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ p->a.isdir = !!S_ISDIR(inode->i_mode);
++ if (unlikely(p->a.isdir && dentry->d_inode
++ && !S_ISDIR(dentry->d_inode->i_mode)))
++ goto out_free;
++
++ aufs_read_and_write_lock2(dentry, src_dentry, p->a.isdir);
++ p->a.dlgt = !!need_dlgt(p->a.sb);
++ p->a.parent[SRC] = p->a.parent[DST] = dentry->d_parent;
++ p->a.issamedir = (src_dir == dir);
++ if (p->a.issamedir)
++ di_write_lock_parent(p->a.parent[DST]);
++ else {
++ p->a.parent[SRC] = src_dentry->d_parent;
++ di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
++ /*isdir*/1);
++ }
++
++ /* which branch we process */
++ p->a.bstart[DST] = dbstart(dentry);
++ p->a.btgt = err = wr_dir(dentry, 1, src_dentry, /*force_btgt*/-1,
++ /*do_lock_srcdir*/0);
++ if (unlikely(err < 0))
++ goto out_unlock;
++
++ /* are they available to be renamed */
++ err = 0;
++ nhash_init(&p->a.whlist);
++ if (p->a.isdir && dentry->d_inode) {
++ set_dbstart(dentry, p->a.bstart[DST]);
++ err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
++ set_dbstart(dentry, p->a.btgt);
++ }
++ p->a.hidden_dentry[DST] = au_h_dptr(dentry);
++ if (unlikely(err))
++ goto out_unlock;
++ //todo: minor optimize, their sb may be same while their bindex differs.
++ p->a.bstart[SRC] = dbstart(src_dentry);
++ p->a.hidden_dentry[SRC] = au_h_dptr(src_dentry);
++ if (p->a.isdir) {
++ err = may_rename_srcdir(src_dentry, p->a.btgt);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ /* prepare the writable parent dir on the same branch */
++ err = wr_dir_need_wh(src_dentry, p->a.isdir, &p->a.btgt,
++ p->a.issamedir ? NULL : p->a.parent[DST]);
++ if (unlikely(err < 0))
++ goto out_children;
++ p->a.whsrc = !!err;
++ p->a.whdst = (p->a.bstart[DST] == p->a.btgt);
++ if (!p->a.whdst) {
++ err = cpup_dirs(dentry, p->a.btgt,
++ p->a.issamedir ? NULL : p->a.parent[SRC]);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ p->a.hidden_parent[SRC] = au_h_dptr_i(p->a.parent[SRC], p->a.btgt);
++ p->a.hidden_parent[DST] = au_h_dptr_i(p->a.parent[DST], p->a.btgt);
++ dirs[0] = src_dir;
++ dirs[1] = dir;
++ hdir_lock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++
++ /* store timestamps to be revertible */
++ dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
++ p->a.hidden_parent[SRC]);
++ if (!p->a.issamedir)
++ dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
++ p->a.hidden_parent[DST]);
++ do_dt_dstdir = 0;
++ if (p->a.isdir) {
++ dtime_store(p->dt[CHILD] + SRC, src_dentry,
++ p->a.hidden_dentry[SRC]);
++ if (p->a.hidden_dentry[DST]->d_inode) {
++ do_dt_dstdir = 1;
++ dtime_store(p->dt[CHILD] + DST, dentry,
++ p->a.hidden_dentry[DST]);
++ }
++ }
++
++ err = do_rename(src_dir, src_dentry, dir, dentry, &p->a);
++ if (unlikely(err))
++ goto out_dt;
++ hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++
++ /* update dir attributes */
++ dir->i_version++;
++ if (p->a.isdir)
++ au_cpup_attr_nlink(dir);
++ if (ibstart(dir) == p->a.btgt)
++ au_cpup_attr_timesizes(dir);
++
++ if (!p->a.issamedir) {
++ src_dir->i_version++;
++ if (p->a.isdir)
++ au_cpup_attr_nlink(src_dir);
++ if (ibstart(src_dir) == p->a.btgt)
++ au_cpup_attr_timesizes(src_dir);
++ }
++
++ // is this updating defined in POSIX?
++ if (unlikely(p->a.isdir)) {
++ //i_lock(inode);
++ au_cpup_attr_timesizes(inode);
++ //i_unlock(inode);
++ }
++
++#if 0
++ d_drop(src_dentry);
++#else
++ /* dput/iput all lower dentries */
++ set_dbwh(src_dentry, -1);
++ bend = dbend(src_dentry);
++ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(src_dentry, bindex);
++ if (hd)
++ set_h_dptr(src_dentry, bindex, NULL);
++ }
++ set_dbend(src_dentry, p->a.btgt);
++
++ bend = ibend(inode);
++ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
++ struct inode *hi;
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi)
++ set_h_iptr(inode, bindex, NULL, 0);
++ }
++ set_ibend(inode, p->a.btgt);
++#endif
++
++#if 0
++ //au_debug_on();
++ //DbgDentry(dentry);
++ //DbgInode(dentry->d_inode);
++ //au_debug_off();
++ inode = dentry->d_inode;
++ if (inode) {
++ aufs_bindex_t bindex, bend;
++ struct dentry *hd;
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ hd = au_h_dptr_i(dentry, bindex);
++ if (hd && hd->d_inode)
++ xino_write0(p->a.sb, bindex, hd->d_inode->i_ino);
++ /* ignore this error */
++ }
++ }
++#endif
++
++ goto out_children; /* success */
++
++ out_dt:
++ dtime_revert(p->dt[PARENT] + SRC,
++ p->a.hidden_parent[SRC]->d_parent
++ == p->a.hidden_parent[DST]);
++ if (!p->a.issamedir)
++ dtime_revert(p->dt[PARENT] + DST,
++ p->a.hidden_parent[DST]->d_parent
++ == p->a.hidden_parent[SRC]);
++ if (p->a.isdir && err != -EIO) {
++ struct dentry *hd;
++
++ hd = p->dt[CHILD][SRC].dt_h_dentry;
++ hi_lock_child(hd->d_inode);
++ dtime_revert(p->dt[CHILD] + SRC, 1);
++ i_unlock(hd->d_inode);
++ if (do_dt_dstdir) {
++ hd = p->dt[CHILD][DST].dt_h_dentry;
++ hi_lock_child(hd->d_inode);
++ dtime_revert(p->dt[CHILD] + DST, 1);
++ i_unlock(hd->d_inode);
++ }
++ }
++ hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++ out_children:
++ nhash_fin(&p->a.whlist);
++ out_unlock:
++ //if (unlikely(err /* && p->a.isdir */)) {
++ if (unlikely(err && p->a.isdir)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ if (p->a.issamedir)
++ di_write_unlock(p->a.parent[DST]);
++ else
++ di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ out_free:
++ kfree(p);
++ out:
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
+new file mode 100755
+index 0000000..9efbd38
+--- /dev/null
++++ b/fs/aufs/iinfo.c
+@@ -0,0 +1,286 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: iinfo.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/mm.h>
++#include "aufs.h"
++
++struct aufs_iinfo *itoii(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++
++ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
++ /* bad_inode case */
++ if (unlikely(!iinfo->ii_hinode))
++ return NULL;
++ DEBUG_ON(!iinfo->ii_hinode
++ /* || stosi(inode->i_sb)->si_bend < iinfo->ii_bend */
++ || iinfo->ii_bend < iinfo->ii_bstart);
++ return iinfo;
++}
++
++aufs_bindex_t ibstart(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ return itoii(inode)->ii_bstart;
++}
++
++aufs_bindex_t ibend(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ return itoii(inode)->ii_bend;
++}
++
++struct aufs_vdir *ivdir(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++ return itoii(inode)->ii_vdir;
++}
++
++struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct inode *hidden_inode;
++
++ IiMustAnyLock(inode);
++ DEBUG_ON(bindex < 0 || ibend(inode) < bindex);
++ hidden_inode = itoii(inode)->ii_hinode[0 + bindex].hi_inode;
++ DEBUG_ON(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
++ return hidden_inode;
++}
++
++struct inode *au_h_iptr(struct inode *inode)
++{
++ return au_h_iptr_i(inode, ibstart(inode));
++}
++
++aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex)
++{
++ IiMustAnyLock(inode);
++ DEBUG_ON(bindex < 0
++ || ibend(inode) < bindex
++ || !itoii(inode)->ii_hinode[0 + bindex].hi_inode);
++ return itoii(inode)->ii_hinode[0 + bindex].hi_id;
++}
++
++// hard/soft set
++void set_ibstart(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct aufs_iinfo *iinfo = itoii(inode);
++ struct inode *h_inode;
++
++ IiMustWriteLock(inode);
++ DEBUG_ON(sbend(inode->i_sb) < bindex);
++ iinfo->ii_bstart = bindex;
++ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
++ if (h_inode)
++ au_cpup_igen(inode, h_inode);
++}
++
++void set_ibend(struct inode *inode, aufs_bindex_t bindex)
++{
++ IiMustWriteLock(inode);
++ DEBUG_ON(sbend(inode->i_sb) < bindex
++ || bindex < ibstart(inode));
++ itoii(inode)->ii_bend = bindex;
++}
++
++void set_ivdir(struct inode *inode, struct aufs_vdir *vdir)
++{
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode)
++ || (itoii(inode)->ii_vdir && vdir));
++ itoii(inode)->ii_vdir = vdir;
++}
++
++void aufs_hiput(struct aufs_hinode *hinode)
++{
++ if (unlikely(hinode->hi_notify))
++ do_free_hinotify(hinode);
++ if (hinode->hi_inode)
++ iput(hinode->hi_inode);
++}
++
++unsigned int au_hi_flags(struct inode *inode, int isdir)
++{
++ unsigned int flags;
++ struct super_block *sb = inode->i_sb;
++
++ flags = 0;
++ if (au_flag_test(sb, AuFlag_XINO))
++ flags = AUFS_HI_XINO;
++ if (unlikely(isdir && au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ flags |= AUFS_HI_NOTIFY;
++ return flags;
++}
++
++void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags)
++{
++ struct aufs_hinode *hinode;
++ struct inode *hi;
++ struct aufs_iinfo *iinfo = itoii(inode);
++
++ LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
++ inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
++ IiMustWriteLock(inode);
++ hinode = iinfo->ii_hinode + bindex;
++ hi = hinode->hi_inode;
++ DEBUG_ON(bindex < ibstart(inode) || ibend(inode) < bindex
++ || (h_inode && atomic_read(&h_inode->i_count) <= 0)
++ || (h_inode && hi));
++
++ if (hi)
++ aufs_hiput(hinode);
++ hinode->hi_inode = h_inode;
++ if (h_inode) {
++ int err;
++ struct super_block *sb = inode->i_sb;
++
++ if (bindex == iinfo->ii_bstart)
++ au_cpup_igen(inode, h_inode);
++ hinode->hi_id = sbr_id(sb, bindex);
++ if (flags & AUFS_HI_XINO) {
++ struct xino xino = {
++ .ino = inode->i_ino,
++ //.h_gen = h_inode->i_generation
++ };
++ //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ err = xino_write(sb, bindex, h_inode->i_ino, &xino);
++ if (unlikely(err)) {
++ IOErr1("failed xino_write() %d, force noxino\n",
++ err);
++ au_flag_clr(sb, AuFlag_XINO);
++ }
++ }
++ if (flags & AUFS_HI_NOTIFY) {
++ err = alloc_hinotify(hinode, inode, h_inode);
++ if (unlikely(err))
++ IOErr1("alloc_hinotify() %d\n", err);
++ else {
++ /* braces are added to stop a warning */
++ DEBUG_ON(!hinode->hi_notify);
++ }
++ }
++ }
++}
++
++void au_update_iigen(struct inode *inode)
++{
++ //IiMustWriteLock(inode);
++ DEBUG_ON(!inode->i_sb);
++ atomic_set(&itoii(inode)->ii_generation, au_sigen(inode->i_sb));
++}
++
++/* it may be called at remount time, too */
++void au_update_brange(struct inode *inode, int do_put_zero)
++{
++ struct aufs_iinfo *iinfo;
++
++ LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
++ IiMustWriteLock(inode);
++
++ iinfo = itoii(inode);
++ if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++) {
++ struct inode *h_i;
++ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
++ if (h_i && !h_i->i_nlink)
++ set_h_iptr(inode, bindex, NULL, 0);
++ }
++ }
++
++ iinfo->ii_bstart = -1;
++ while (++iinfo->ii_bstart <= iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
++ break;
++ if (iinfo->ii_bstart > iinfo->ii_bend) {
++ iinfo->ii_bend = iinfo->ii_bstart = -1;
++ return;
++ }
++
++ iinfo->ii_bend++;
++ while (0 <= --iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
++ break;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_iinfo_init(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++ struct super_block *sb;
++ int nbr, i;
++
++ sb = inode->i_sb;
++ DEBUG_ON(!sb);
++ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
++ DEBUG_ON(iinfo->ii_hinode);
++ nbr = sbend(sb) + 1;
++ if (unlikely(!nbr))
++ nbr++;
++ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
++ //iinfo->ii_hinode = NULL;
++ if (iinfo->ii_hinode) {
++ for (i = 0; i < nbr; i++)
++ iinfo->ii_hinode[i].hi_id = -1;
++ atomic_set(&iinfo->ii_generation, au_sigen(sb));
++ rw_init_nolock(&iinfo->ii_rwsem);
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ iinfo->ii_vdir = NULL;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++void au_iinfo_fin(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++
++ iinfo = itoii(inode);
++ /* bad_inode case */
++ if (unlikely(!iinfo))
++ return;
++
++ if (unlikely(iinfo->ii_vdir))
++ free_vdir(iinfo->ii_vdir);
++
++ if (iinfo->ii_bstart >= 0) {
++ aufs_bindex_t bend;
++ struct aufs_hinode *hi;
++ hi = iinfo->ii_hinode + iinfo->ii_bstart;
++ bend = iinfo->ii_bend;
++ while (iinfo->ii_bstart++ <= bend) {
++ if (hi->hi_inode)
++ aufs_hiput(hi);
++ hi++;
++ }
++ //iinfo->ii_bstart = iinfo->ii_bend = -1;
++ }
++
++ kfree(iinfo->ii_hinode);
++ //iinfo->ii_hinode = NULL;
++}
+diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c
+new file mode 100755
+index 0000000..f18b5d8
+--- /dev/null
++++ b/fs/aufs/inode.c
+@@ -0,0 +1,339 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: inode.c,v 1.22 2007/05/07 03:44:35 sfjro Exp $ */
++
++#include "aufs.h"
++
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
++{
++ int err, new_sz, update, isdir;
++ struct inode *first;
++ struct aufs_hinode *p, *q, tmp;
++ struct super_block *sb;
++ struct aufs_iinfo *iinfo;
++ aufs_bindex_t bindex, bend, new_bindex;
++ unsigned int flags;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ IiMustWriteLock(inode);
++
++ err = -ENOMEM;
++ sb = dentry->d_sb;
++ bend = sbend(sb);
++ new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
++ iinfo = itoii(inode);
++ p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++
++ iinfo->ii_hinode = p;
++ err = 0;
++ update = 0;
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++, p++) {
++ if (unlikely(!p->hi_inode))
++ continue;
++
++ new_bindex = find_brindex(sb, p->hi_id);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) {
++ update++;
++ aufs_hiput(p);
++ p->hi_inode = NULL;
++ continue;
++ }
++
++ if (new_bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = new_bindex;
++ if (iinfo->ii_bend < new_bindex)
++ iinfo->ii_bend = new_bindex;
++ /* swap two hidden inode, and loop again */
++ q = iinfo->ii_hinode + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hi_inode) {
++ bindex--;
++ p--;
++ }
++ }
++
++ isdir = S_ISDIR(inode->i_mode);
++ flags = au_hi_flags(inode, isdir);
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ struct inode *hi;
++ struct dentry *hd;
++
++ hd = au_h_dptr_i(dentry, bindex);
++ if (!hd || !hd->d_inode)
++ continue;
++
++ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi) {
++ if (hi == hd->d_inode)
++ continue;
++ //Dbg("here\n");
++ err = -ESTALE;
++ break;
++ }
++ }
++ if (bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = bindex;
++ if (iinfo->ii_bend < bindex)
++ iinfo->ii_bend = bindex;
++ set_h_iptr(inode, bindex, igrab(hd->d_inode), flags);
++ update++;
++ }
++
++ bend = iinfo->ii_bend;
++ p = iinfo->ii_hinode;
++ for (bindex = 0; bindex <= bend; bindex++, p++)
++ if (p->hi_inode) {
++ iinfo->ii_bstart = bindex;
++ break;
++ }
++ p = iinfo->ii_hinode + bend;
++ for (bindex = bend; bindex > iinfo->ii_bstart; bindex--, p--)
++ if (p->hi_inode) {
++ iinfo->ii_bend = bindex;
++ break;
++ }
++ DEBUG_ON(iinfo->ii_bstart > bend || iinfo->ii_bend < 0);
++
++ if (unlikely(err))
++ goto out;
++
++ if (1 || first != au_h_iptr(inode))
++ au_cpup_attr_all(inode);
++ if (update && isdir)
++ inode->i_version++;
++ au_update_iigen(inode);
++
++ out:
++ //au_debug_on();
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++static int set_inode(struct inode *inode, struct dentry *dentry)
++{
++ int err, isdir;
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++ umode_t mode;
++ aufs_bindex_t bindex, bstart, btail;
++ struct aufs_iinfo *iinfo;
++ unsigned int flags;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++ DEBUG_ON(!(inode->i_state & I_NEW));
++ IiMustWriteLock(inode);
++ hidden_dentry = au_h_dptr(dentry);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ err = 0;
++ isdir = 0;
++ bstart = dbstart(dentry);
++ mode = hidden_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ btail = dbtail(dentry);
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ btail = dbtaildir(dentry);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ break;
++ case S_IFLNK:
++ btail = dbtail(dentry);
++ inode->i_op = &aufs_symlink_iop;
++ break;
++ case S_IFBLK:
++ case S_IFCHR:
++ case S_IFIFO:
++ case S_IFSOCK:
++ btail = dbtail(dentry);
++ init_special_inode(inode, mode, hidden_inode->i_rdev);
++ break;
++ default:
++ IOErr("Unknown file type 0%o\n", mode);
++ err = -EIO;
++ goto out;
++ }
++
++ flags = au_hi_flags(inode, isdir);
++ iinfo = itoii(inode);
++ iinfo->ii_bstart = bstart;
++ iinfo->ii_bend = btail;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ DEBUG_ON(!hidden_dentry->d_inode);
++ set_h_iptr(inode, bindex, igrab(hidden_dentry->d_inode), flags);
++ }
++ au_cpup_attr_all(inode);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++//todo: return with unlocked?
++static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
++{
++ int err;
++ struct inode *h_inode, *h_dinode;
++ aufs_bindex_t bindex, bend;
++ //const int udba = !au_flag_test(inode->i_sb, AuFlag_UDBA_NONE);
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++
++ *matched = 0;
++
++ /*
++ * before this function, if aufs got any iinfo lock, it must be only
++ * one, the parent dir.
++ * it can happen by UDBA and the obsoleted inode number.
++ */
++ err = -EIO;
++ if (unlikely(inode->i_ino == parent_ino(dentry)))
++ goto out;
++
++ h_dinode = au_h_dptr(dentry)->d_inode;
++ hi_lock_child(inode); // bad name, this is not a hidden inode.
++ ii_write_lock_new(inode);
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); bindex <= bend; bindex++) {
++ h_inode = au_h_iptr_i(inode, bindex);
++ if (h_inode && h_inode == h_dinode) {
++ //&& (ibs != bstart || !au_test_higen(inode, h_inode)));
++ *matched = 1;
++ err = 0;
++ if (unlikely(au_iigen(inode) != au_digen(dentry)))
++ err = au_refresh_hinode(inode, dentry);
++ break;
++ }
++ }
++ i_unlock(inode);
++ if (unlikely(err))
++ ii_write_unlock(inode);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++//todo: return with unlocked?
++struct inode *au_new_inode(struct dentry *dentry)
++{
++ struct inode *inode, *h_inode;
++ struct dentry *h_dentry;
++ ino_t h_ino;
++ struct super_block *sb;
++ int err, match;
++ aufs_bindex_t bstart;
++ struct xino xino;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ sb = dentry->d_sb;
++ h_dentry = au_h_dptr(dentry);
++ DEBUG_ON(!h_dentry);
++ h_inode = h_dentry->d_inode;
++ DEBUG_ON(!h_inode);
++
++ bstart = dbstart(dentry);
++ h_ino = h_inode->i_ino;
++ err = xino_read(sb, bstart, h_ino, &xino);
++ //err = -1;
++ inode = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++ new_ino:
++ if (!xino.ino) {
++ xino.ino = xino_new_ino(sb);
++ if (!xino.ino) {
++ inode = ERR_PTR(-EIO);
++ goto out;
++ }
++ }
++
++ LKTRTrace("i%lu\n", xino.ino);
++ err = -ENOMEM;
++ inode = iget_locked(sb, xino.ino);
++ if (unlikely(!inode))
++ goto out;
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++ err = -ENOMEM;
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
++ if (inode->i_state & I_NEW) {
++ sb->s_op->read_inode(inode);
++ if (!is_bad_inode(inode)) {
++ ii_write_lock_new(inode);
++ err = set_inode(inode, dentry);
++ //err = -1;
++ }
++ unlock_new_inode(inode);
++ if (!err)
++ goto out; /* success */
++ ii_write_unlock(inode);
++ goto out_iput;
++ } else {
++ err = reval_inode(inode, dentry, &match);
++ if (!err)
++ goto out; /* success */
++ else if (match)
++ goto out_iput;
++ }
++
++ Warn1("broken ino, b%d, %.*s/%.*s, hi%lu, i%lu. Try udba=inotify.\n",
++ bstart, DLNPair(dentry->d_parent), DLNPair(dentry), h_ino,
++ xino.ino);
++ xino.ino = 0;
++ err = xino_write0(sb, bstart, h_ino);
++ if (!err) {
++ iput(inode);
++ goto new_ino;
++ }
++
++ out_iput:
++ iput(inode);
++ inode = ERR_PTR(err);
++ out:
++ TraceErrPtr(inode);
++ return inode;
++}
+diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h
+new file mode 100755
+index 0000000..b001ac3
+--- /dev/null
++++ b/fs/aufs/inode.h
+@@ -0,0 +1,377 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: inode.h,v 1.32 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_INODE_H__
++#define __AUFS_INODE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/inotify.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "vfsub.h"
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#else
++struct inotify_watch {};
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_hinotify {
++ struct inotify_watch hin_watch;
++ struct inode *hin_aufs_inode; /* no get/put */
++};
++
++struct aufs_hinode {
++ struct inode *hi_inode;
++ aufs_bindex_t hi_id;
++ struct aufs_hinotify *hi_notify;
++};
++
++struct aufs_vdir;
++struct aufs_iinfo {
++ atomic_t ii_generation;
++ struct super_block *ii_hsb1; /* no get/put */
++
++ struct aufs_rwsem ii_rwsem;
++ aufs_bindex_t ii_bstart, ii_bend;
++ struct aufs_hinode *ii_hinode;
++ struct aufs_vdir *ii_vdir;
++};
++
++struct aufs_icntnr {
++ struct aufs_iinfo iinfo;
++ struct inode vfs_inode;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* inode.c */
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
++struct inode *au_new_inode(struct dentry *dentry);
++
++/* i_op.c */
++extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
++int wr_dir(struct dentry *dentry, int negative, struct dentry *src_dentry,
++ aufs_bindex_t force_btgt, int do_lock_srcdir);
++
++/* i_op_del.c */
++int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dentry *locked);
++
++/* iinfo.c */
++struct aufs_iinfo *itoii(struct inode *inode);
++aufs_bindex_t ibstart(struct inode *inode);
++aufs_bindex_t ibend(struct inode *inode);
++struct aufs_vdir *ivdir(struct inode *inode);
++struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex);
++struct inode *au_h_iptr(struct inode *inode);
++aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex);
++
++void set_ibstart(struct inode *inode, aufs_bindex_t bindex);
++void set_ibend(struct inode *inode, aufs_bindex_t bindex);
++void set_ivdir(struct inode *inode, struct aufs_vdir *vdir);
++void aufs_hiput(struct aufs_hinode *hinode);
++#define AUFS_HI_XINO 1
++#define AUFS_HI_NOTIFY 2
++unsigned int au_hi_flags(struct inode *inode, int isdir);
++void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags);
++void au_update_iigen(struct inode *inode);
++void au_update_brange(struct inode *inode, int do_put_zero);
++
++int au_iinfo_init(struct inode *inode);
++void au_iinfo_fin(struct inode *inode);
++
++/* plink.c */
++#ifdef CONFIG_AUFS_DEBUG
++void au_list_plink(struct super_block *sb);
++#else
++static inline void au_list_plink(struct super_block *sb)
++{
++ /* nothing */
++}
++#endif
++int au_is_plinked(struct super_block *sb, struct inode *inode);
++struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode);
++void append_plink(struct super_block *sb, struct inode *inode,
++ struct dentry *h_dentry, aufs_bindex_t bindex);
++void au_put_plink(struct super_block *sb);
++void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id);
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for hidden inode */
++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
++// todo: reduce it by dcsub.
++enum {
++ AuLsc_Begin = I_MUTEX_QUOTA,
++ AuLsc_HI_GPARENT, /* setattr with inotify */
++ AuLsc_HI_PARENT, /* hidden inode, parent first */
++ AuLsc_HI_CHILD,
++ AuLsc_HI_PARENT2, /* copyup dirs */
++ AuLsc_HI_CHILD2,
++ AuLsc_End
++};
++
++/* simple abstraction */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++static inline void i_lock(struct inode *i)
++{
++ down(&i->i_sem);
++}
++
++static inline void i_unlock(struct inode *i)
++{
++ up(&i->i_sem);
++}
++
++static inline int i_trylock(struct inode *i)
++{
++ return down_trylock(&i->i_sem);
++}
++
++static inline void hi_lock(struct inode *i, unsigned int lsc)
++{
++ i_lock(i);
++}
++
++#define IMustLock(i) DEBUG_ON(!down_trylock(&(i)->i_sem))
++#else
++static inline void i_lock(struct inode *i)
++{
++ mutex_lock(&i->i_mutex);
++}
++
++static inline void i_unlock(struct inode *i)
++{
++ mutex_unlock(&i->i_mutex);
++}
++
++static inline int i_trylock(struct inode *i)
++{
++ return mutex_trylock(&i->i_mutex);
++}
++
++static inline void hi_lock(struct inode *i, unsigned int lsc)
++{
++ mutex_lock_nested(&i->i_mutex, lsc);
++}
++
++#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
++#endif
++
++/*
++ * hi_lock_gparent, hi_lock_parent, hi_lock_parent2, hi_lock_child,
++ * hi_lock_child2, hi_lock_whplink
++ */
++#define LockFunc(name, lsc) \
++static inline void hi_lock_##name(struct inode *h_i) \
++{hi_lock(h_i, AuLsc_HI_##lsc);}
++
++LockFunc(gparent, GPARENT);
++LockFunc(parent, PARENT);
++LockFunc(parent2, PARENT2);
++LockFunc(child, CHILD);
++LockFunc(child2, CHILD2);
++LockFunc(whplink, CHILD2); /* sharing lock-subclass */
++
++#undef LockFunc
++
++/* ---------------------------------------------------------------------- */
++
++/* tiny test for inode number */
++/* tmpfs generation is too rough */
++static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
++{
++ //IiMustAnyLock(inode);
++ return !(itoii(inode)->ii_hsb1 == h_inode->i_sb
++ && inode->i_generation == h_inode->i_generation);
++}
++
++static inline int au_iigen(struct inode *inode)
++{
++ return atomic_read(&itoii(inode)->ii_generation);
++}
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_iigen_dec(struct inode *inode)
++{
++ //Dbg("i%lu\n", inode->i_ino);
++ atomic_dec(&itoii(inode)->ii_generation);
++}
++
++/* hinotify.c */
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *h_inode);
++void do_free_hinotify(struct aufs_hinode *hinode);
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc);
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex);
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir);
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir);
++void au_reset_hinotify(struct inode *inode, unsigned int flags);
++int __init au_inotify_init(void);
++void au_inotify_fin(void);
++#else
++static inline
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *h_inode)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline void do_free_hinotify(struct aufs_hinode *hinode)
++{
++ /* nothing */
++}
++
++static inline
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc)
++{
++ hi_lock(h_dir, lsc);
++}
++
++static inline
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
++{
++ i_unlock(h_dir);
++}
++
++static inline
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ vfsub_lock_rename(h_parents[0], h_parents[1]);
++}
++
++static inline
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ vfsub_unlock_rename(h_parents[0], h_parents[1]);
++}
++
++static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ /* nothing */
++}
++
++#define au_inotify_init() 0
++#define au_inotify_fin() /* */
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++static inline void free_hinotify(struct inode *inode, aufs_bindex_t bindex)
++{
++ do_free_hinotify(itoii(inode)->ii_hinode + bindex);
++}
++
++/*
++ * hgdir_lock, hdir_lock, hdir2_lock
++ */
++#define LockFunc(name, lsc) \
++static inline \
++void name##_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex) \
++{do_hdir_lock(h_dir, dir, bindex, AuLsc_HI_##lsc);}
++
++LockFunc(hgdir, GPARENT);
++LockFunc(hdir, PARENT);
++LockFunc(hdir2, PARENT2);
++
++#undef LockFunc
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for iinfo */
++enum {
++ AuLsc_II_CHILD, /* child first */
++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_II_CHILD3, /* copyup dirs */
++ AuLsc_II_PARENT,
++ AuLsc_II_PARENT2,
++ AuLsc_II_PARENT3,
++ AuLsc_II_NEW /* new inode */
++};
++
++/*
++ * ii_read_lock_child, ii_write_lock_child,
++ * ii_read_lock_child2, ii_write_lock_child2,
++ * ii_read_lock_child3, ii_write_lock_child3,
++ * ii_read_lock_parent, ii_write_lock_parent,
++ * ii_read_lock_parent2, ii_write_lock_parent2,
++ * ii_read_lock_parent3, ii_write_lock_parent3,
++ * ii_read_lock_new, ii_write_lock_new
++ */
++#define ReadLockFunc(name, lsc) \
++static inline void ii_read_lock_##name(struct inode *i) \
++{rw_read_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
++
++#define WriteLockFunc(name, lsc) \
++static inline void ii_write_lock_##name(struct inode *i) \
++{rw_write_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
++
++#define RWLockFuncs(name, lsc) \
++ ReadLockFunc(name, lsc); \
++ WriteLockFunc(name, lsc)
++
++RWLockFuncs(child, CHILD);
++RWLockFuncs(child2, CHILD2);
++RWLockFuncs(child3, CHILD3);
++RWLockFuncs(parent, PARENT);
++RWLockFuncs(parent2, PARENT2);
++RWLockFuncs(parent3, PARENT3);
++RWLockFuncs(new, NEW);
++
++#undef ReadLockFunc
++#undef WriteLockFunc
++#undef RWLockFunc
++
++/*
++ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
++ */
++SimpleUnlockRwsemFuncs(ii, struct inode *i, itoii(i)->ii_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define IiMustReadLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustReadLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustWriteLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustWriteLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustAnyLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustAnyLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustNoWaiters(i) RwMustNoWaiters(&itoii(i)->ii_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_INODE_H__ */
+diff --git a/fs/aufs/misc.c b/fs/aufs/misc.c
+new file mode 100755
+index 0000000..32e0549
+--- /dev/null
++++ b/fs/aufs/misc.c
+@@ -0,0 +1,228 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: misc.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++//#include <linux/mm.h>
++//#include <asm/uaccess.h>
++#include "aufs.h"
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
++{
++ void *q;
++
++ LKTRTrace("p %p, nused %d, sz %d, ksize %d\n",
++ p, nused, new_sz, ksize(p));
++ DEBUG_ON(new_sz <= 0);
++ if (new_sz <= nused)
++ return p;
++ if (new_sz <= ksize(p)) {
++ memset(p + nused, 0, new_sz - nused);
++ return p;
++ }
++
++ q = kmalloc(new_sz, gfp);
++ //q = NULL;
++ if (unlikely(!q))
++ return NULL;
++ memcpy(q, p, nused);
++ memset(q + nused, 0, new_sz - nused);
++ //smp_mb();
++ kfree(p);
++ return q;
++}
++
++/* ---------------------------------------------------------------------- */
++
++// todo: make it inline
++struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
++ struct super_block *sb, aufs_bindex_t bindex)
++{
++ LKTRTrace("nd %p, b%d\n", nd, bindex);
++
++ if (!nd)
++ return NULL;
++
++ fake_nd->dentry = NULL;
++ fake_nd->mnt = NULL;
++
++#ifndef CONFIG_AUFS_FAKE_DM
++ DiMustAnyLock(nd->dentry);
++
++ if (bindex <= dbend(nd->dentry))
++ fake_nd->dentry = au_h_dptr_i(nd->dentry, bindex);
++ if (fake_nd->dentry) {
++ dget(fake_nd->dentry);
++ fake_nd->mnt = sbr_mnt(sb, bindex);
++ DEBUG_ON(!fake_nd->mnt);
++ mntget(fake_nd->mnt);
++ } else
++ fake_nd = ERR_PTR(-ENOENT);
++#endif
++
++ TraceErrPtr(fake_nd);
++ return fake_nd;
++}
++
++void fake_dm_release(struct nameidata *fake_nd)
++{
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (fake_nd) {
++ mntput(fake_nd->mnt);
++ dput(fake_nd->dentry);
++ }
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len,
++ struct super_block *sb, int *sparse)
++{
++ int err, all_zero, dlgt;
++ unsigned long blksize;
++ char *buf;
++ /* reduce stack space */
++ struct iattr *ia;
++
++ LKTRTrace("%.*s, %.*s\n",
++ DLNPair(dst->f_dentry), DLNPair(src->f_dentry));
++ DEBUG_ON(!(dst->f_mode & FMODE_WRITE));
++ IMustLock(dst->f_dentry->d_parent->d_inode);
++
++ err = -ENOMEM;
++ blksize = dst->f_dentry->d_sb->s_blocksize;
++ if (!blksize || PAGE_SIZE < blksize)
++ blksize = PAGE_SIZE;
++ LKTRTrace("blksize %lu\n", blksize);
++ buf = kmalloc(blksize, GFP_KERNEL);
++ //buf = NULL;
++ if (unlikely(!buf))
++ goto out;
++ ia = kmalloc(sizeof(*ia), GFP_KERNEL);
++ if (unlikely(!ia))
++ goto out_buf;
++
++ dlgt = need_dlgt(sb);
++ err = all_zero = 0;
++ dst->f_pos = src->f_pos = 0;
++ while (len) {
++ size_t sz, rbytes, wbytes, i;
++ char *p;
++
++ LKTRTrace("len %lld\n", len);
++ sz = blksize;
++ if (len < blksize)
++ sz = len;
++
++ /* support LSM and notify */
++ rbytes = 0;
++ while (!rbytes || err == -EAGAIN || err == -EINTR)
++ err = rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
++ dlgt);
++ if (unlikely(err < 0))
++ break;
++
++ all_zero = 0;
++ if (len >= rbytes && rbytes == blksize) {
++ all_zero = 1;
++ p = buf;
++ for (i = 0; all_zero && i < rbytes; i++)
++ all_zero = !*p++;
++ }
++ if (!all_zero) {
++ wbytes = rbytes;
++ p = buf;
++ while (wbytes) {
++ size_t b;
++ /* support LSM and notify */
++ err = b = vfsub_write_k(dst, p, wbytes,
++ &dst->f_pos, dlgt);
++ if (unlikely(err == -EAGAIN || err == -EINTR))
++ continue;
++ if (unlikely(err < 0))
++ break;
++ wbytes -= b;
++ p += b;
++ }
++ } else {
++ loff_t res;
++ LKTRLabel(hole);
++ *sparse = 1;
++ err = res = vfsub_llseek(dst, rbytes, SEEK_CUR);
++ if (unlikely(res < 0))
++ break;
++ }
++ len -= rbytes;
++ err = 0;
++ }
++
++ /* the last block may be a hole */
++ if (unlikely(!err && all_zero)) {
++ struct dentry *h_d = dst->f_dentry;
++ struct inode *h_i = h_d->d_inode;
++
++ LKTRLabel(last hole);
++ do {
++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, dlgt);
++ } while (err == -EAGAIN || err == -EINTR);
++ if (err == 1) {
++ ia->ia_size = dst->f_pos;
++ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
++ ia->ia_file = dst;
++ hi_lock_child2(h_i);
++ err = vfsub_notify_change(h_d, ia, dlgt);
++ i_unlock(h_i);
++ }
++ }
++
++ kfree(ia);
++ out_buf:
++ kfree(buf);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode)
++{
++ int err;
++
++ err = br_rdonly(stobr(sb, bindex));
++ if (!err && inode) {
++ struct inode *hi = au_h_iptr_i(inode, bindex);
++ if (hi)
++ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
++ }
++ return err;
++}
++
++int au_test_perm(struct inode *hidden_inode, int mask, int dlgt)
++{
++ if (!current->fsuid)
++ return 0;
++ if (unlikely(au_is_nfs(hidden_inode->i_sb)
++ && (mask & MAY_WRITE)
++ && S_ISDIR(hidden_inode->i_mode)))
++ mask |= MAY_READ; /* force permission check */
++ return vfsub_permission(hidden_inode, mask, NULL, dlgt);
++}
+diff --git a/fs/aufs/misc.h b/fs/aufs/misc.h
+new file mode 100755
+index 0000000..fea4a2c
+--- /dev/null
++++ b/fs/aufs/misc.h
+@@ -0,0 +1,187 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: misc.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_MISC_H__
++#define __AUFS_MISC_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/sched.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#define I_MUTEX_QUOTA 0
++#define lockdep_off() /* */
++#define lockdep_on() /* */
++#define mutex_lock_nested(mtx, lsc) mutex_lock(mtx)
++#define down_write_nested(rw, lsc) down_write(rw)
++#define down_read_nested(rw, lsc) down_read(rw)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_rwsem {
++ struct rw_semaphore rwsem;
++#ifdef CONFIG_AUFS_DEBUG
++ atomic_t rcnt;
++#endif
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++#define DbgRcntInit(rw) atomic_set(&(rw)->rcnt, 0)
++#define DbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
++#define DbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
++#else
++#define DbgRcntInit(rw) /* */
++#define DbgRcntInc(rw) /* */
++#define DbgRcntDec(rw) /* */
++#endif
++
++static inline void rw_init_nolock(struct aufs_rwsem *rw)
++{
++ DbgRcntInit(rw);
++ init_rwsem(&rw->rwsem);
++}
++
++static inline void rw_init_wlock(struct aufs_rwsem *rw)
++{
++ rw_init_nolock(rw);
++ down_write(&rw->rwsem);
++}
++
++static inline void rw_init_wlock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ rw_init_nolock(rw);
++ down_write_nested(&rw->rwsem, lsc);
++}
++
++static inline void rw_read_lock(struct aufs_rwsem *rw)
++{
++ down_read(&rw->rwsem);
++ DbgRcntInc(rw);
++}
++
++static inline void rw_read_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ down_read_nested(&rw->rwsem, lsc);
++ DbgRcntInc(rw);
++}
++
++static inline void rw_read_unlock(struct aufs_rwsem *rw)
++{
++ DbgRcntDec(rw);
++ up_read(&rw->rwsem);
++}
++
++static inline void rw_dgrade_lock(struct aufs_rwsem *rw)
++{
++ DbgRcntInc(rw);
++ downgrade_write(&rw->rwsem);
++}
++
++static inline void rw_write_lock(struct aufs_rwsem *rw)
++{
++ down_write(&rw->rwsem);
++}
++
++static inline void rw_write_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ down_write_nested(&rw->rwsem, lsc);
++}
++
++static inline void rw_write_unlock(struct aufs_rwsem *rw)
++{
++ up_write(&rw->rwsem);
++}
++
++#if 0 // why is not _nested version defined
++static inline int rw_read_trylock(struct aufs_rwsem *rw)
++{
++ int ret = down_read_trylock(&rw->rwsem);
++ if (ret)
++ DbgRcntInc(rw);
++ return ret;
++}
++
++static inline int rw_write_trylock(struct aufs_rwsem *rw)
++{
++ return down_write_trylock(&rw->rwsem);
++}
++#endif
++
++#undef DbgRcntInit
++#undef DbgRcntInc
++#undef DbgRcntDec
++
++/* to debug easier, do not make them inlined functions */
++#define RwMustNoWaiters(rw) DEBUG_ON(!list_empty(&(rw)->rwsem.wait_list))
++#define RwMustAnyLock(rw) DEBUG_ON(down_write_trylock(&(rw)->rwsem))
++#ifdef CONFIG_AUFS_DEBUG
++#define RwMustReadLock(rw) do { \
++ RwMustAnyLock(rw); \
++ DEBUG_ON(!atomic_read(&(rw)->rcnt)); \
++} while (0)
++#define RwMustWriteLock(rw) do { \
++ RwMustAnyLock(rw); \
++ DEBUG_ON(atomic_read(&(rw)->rcnt)); \
++} while (0)
++#else
++#define RwMustReadLock(rw) RwMustAnyLock(rw)
++#define RwMustWriteLock(rw) RwMustAnyLock(rw)
++#endif
++
++#define SimpleLockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_lock(param) {rw_read_lock(&(rwsem));} \
++static inline void prefix##_write_lock(param) {rw_write_lock(&(rwsem));}
++//static inline void prefix##_read_trylock(param) {rw_read_trylock(&(rwsem));}
++//static inline void prefix##_write_trylock(param) {rw_write_trylock(&(rwsem));}
++//static inline void prefix##_read_trylock_nested(param, lsc)
++//{rw_read_trylock_nested(&(rwsem, lsc));}
++//static inline void prefix##_write_trylock_nestd(param, lsc)
++//{rw_write_trylock_nested(&(rwsem), nested);}
++
++#define SimpleUnlockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_unlock(param) {rw_read_unlock(&(rwsem));} \
++static inline void prefix##_write_unlock(param) {rw_write_unlock(&(rwsem));} \
++static inline void prefix##_downgrade_lock(param) {rw_dgrade_lock(&(rwsem));}
++
++#define SimpleRwsemFuncs(prefix, param, rwsem) \
++ SimpleLockRwsemFuncs(prefix, param, rwsem); \
++ SimpleUnlockRwsemFuncs(prefix, param, rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++typedef ssize_t (*readf_t)(struct file*, char __user*, size_t, loff_t*);
++typedef ssize_t (*writef_t)(struct file*, const char __user*, size_t, loff_t*);
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
++struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
++ struct super_block *sb, aufs_bindex_t bindex);
++void fake_dm_release(struct nameidata *fake_nd);
++int au_copy_file(struct file *dst, struct file *src, loff_t len,
++ struct super_block *sb, int *sparse);
++int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode);
++int au_test_perm(struct inode *h_inode, int mask, int dlgt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MISC_H__ */
+diff --git a/fs/aufs/module.c b/fs/aufs/module.c
+new file mode 100755
+index 0000000..06c563e
+--- /dev/null
++++ b/fs/aufs/module.c
+@@ -0,0 +1,334 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: module.c,v 1.9 2007/04/30 05:46:32 sfjro Exp $ */
++
++//#include <linux/init.h>
++//#include <linux/kobject.h>
++#include <linux/module.h>
++//#include <linux/seq_file.h>
++//#include <linux/sysfs.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * aufs caches
++ */
++struct kmem_cache *aufs_cachep[AuCache_Last];
++static int __init create_cache(void)
++{
++#define Cache(type) kmem_cache_create(#type, sizeof(struct type), 0, \
++ SLAB_RECLAIM_ACCOUNT, NULL, NULL)
++
++ if ((aufs_cachep[AuCache_DINFO] = Cache(aufs_dinfo))
++ && (aufs_cachep[AuCache_ICNTNR] = Cache(aufs_icntnr))
++ && (aufs_cachep[AuCache_FINFO] = Cache(aufs_finfo))
++ //&& (aufs_cachep[AuCache_FINFO] = NULL)
++ && (aufs_cachep[AuCache_VDIR] = Cache(aufs_vdir))
++ && (aufs_cachep[AuCache_DEHSTR] = Cache(aufs_dehstr))
++ && (aufs_cachep[AuCache_HINOTIFY] = Cache(aufs_hinotify)))
++ return 0;
++ return -ENOMEM;
++
++#undef Cache
++}
++
++static void destroy_cache(void)
++{
++ int i;
++ for (i = 0; i < AuCache_Last; i++)
++ if (aufs_cachep[i])
++ kmem_cache_destroy(aufs_cachep[i]);
++}
++
++/* ---------------------------------------------------------------------- */
++
++char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
++int au_dir_roflags;
++extern struct file_system_type aufs_fs_type;
++
++#ifdef DbgDlgt
++#include <linux/security.h>
++#include "dbg_dlgt.c"
++#else
++#define dbg_dlgt_init() 0
++#define dbg_dlgt_fin() /* */
++#endif
++
++/*
++ * functions for module interface.
++ */
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Junjiro Okajima");
++MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
++MODULE_VERSION(AUFS_VERSION);
++
++/* it should be 'byte', but param_set_byte() prints by "%c" */
++short aufs_nwkq = AUFS_NWKQ_DEF;
++MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
++module_param_named(nwkq, aufs_nwkq, short, 0444);
++
++int sysaufs_brs = 0;
++MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/brs");
++module_param_named(brs, sysaufs_brs, int, 0444);
++
++static int __init aufs_init(void)
++{
++ int err, i;
++ char *p;
++
++ //sbinfo->si_xino is atomic_long_t
++ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
++
++#ifdef CONFIG_AUFS_DEBUG
++ {
++ struct aufs_destr destr;
++ destr.len = -1;
++ DEBUG_ON(destr.len < NAME_MAX);
++ }
++
++#ifdef CONFIG_4KSTACKS
++ printk("CONFIG_4KSTACKS is defined.\n");
++#endif
++#if 0 // verbose debug
++ {
++ union {
++ struct aufs_branch *br;
++ struct aufs_dinfo *di;
++ struct aufs_finfo *fi;
++ struct aufs_iinfo *ii;
++ struct aufs_hinode *hi;
++ struct aufs_sbinfo *si;
++ struct aufs_destr *destr;
++ struct aufs_de *de;
++ struct aufs_wh *wh;
++ struct aufs_vdir *vd;
++ } u;
++
++ printk("br{"
++ "xino %d, readf %d, writef %d, "
++ "id %d, perm %d, mnt %d, count %d, "
++ "wh_sem %d, wh %d, run %d} %d\n",
++ offsetof(typeof(*u.br), br_xino),
++ offsetof(typeof(*u.br), br_xino_read),
++ offsetof(typeof(*u.br), br_xino_write),
++ offsetof(typeof(*u.br), br_id),
++ offsetof(typeof(*u.br), br_perm),
++ offsetof(typeof(*u.br), br_mnt),
++ offsetof(typeof(*u.br), br_count),
++ offsetof(typeof(*u.br), br_wh_rwsem),
++ offsetof(typeof(*u.br), br_wh),
++ offsetof(typeof(*u.br), br_wh_running),
++ sizeof(*u.br));
++ printk("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, "
++ "bdiropq %d, hdentry %d, reval %d} %d\n",
++ offsetof(typeof(*u.di), di_generation),
++ offsetof(typeof(*u.di), di_rwsem),
++ offsetof(typeof(*u.di), di_bstart),
++ offsetof(typeof(*u.di), di_bend),
++ offsetof(typeof(*u.di), di_bwh),
++ offsetof(typeof(*u.di), di_bdiropq),
++ offsetof(typeof(*u.di), di_hdentry),
++ offsetof(typeof(*u.di), di_reval),
++ sizeof(*u.di));
++ printk("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, "
++ "h_vm_ops %d, vdir_cach %d} %d\n",
++ offsetof(typeof(*u.fi), fi_generation),
++ offsetof(typeof(*u.fi), fi_rwsem),
++ offsetof(typeof(*u.fi), fi_hfile),
++ offsetof(typeof(*u.fi), fi_bstart),
++ offsetof(typeof(*u.fi), fi_bend),
++ offsetof(typeof(*u.fi), fi_h_vm_ops),
++ offsetof(typeof(*u.fi), fi_vdir_cache),
++ sizeof(*u.fi));
++ printk("ii{rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} "
++ "%d\n",
++ offsetof(typeof(*u.ii), ii_rwsem),
++ offsetof(typeof(*u.ii), ii_bstart),
++ offsetof(typeof(*u.ii), ii_bend),
++ offsetof(typeof(*u.ii), ii_hinode),
++ offsetof(typeof(*u.ii), ii_vdir),
++ sizeof(*u.ii));
++ printk("hi{inode %d, id %d, notify %d} %d\n",
++ offsetof(typeof(*u.hi), hi_inode),
++ offsetof(typeof(*u.hi), hi_id),
++ offsetof(typeof(*u.hi), hi_notify),
++ sizeof(*u.hi));
++ printk("si{rwsem %d, gen %d, "
++ "failed_refresh %d, "
++ "bend %d, last id %d, br %d, "
++ "flags %d, "
++ "xino %d, "
++ "rdcache %d, "
++ "dirwh %d, "
++ "pl_lock %d, pl %d, "
++ "kobj %d} %d\n",
++ offsetof(typeof(*u.si), si_rwsem),
++ offsetof(typeof(*u.si), si_generation),
++ -1,//offsetof(typeof(*u.si), si_failed_refresh_dirs),
++ offsetof(typeof(*u.si), si_bend),
++ offsetof(typeof(*u.si), si_last_br_id),
++ offsetof(typeof(*u.si), si_branch),
++ offsetof(typeof(*u.si), si_flags),
++ offsetof(typeof(*u.si), si_xino),
++ offsetof(typeof(*u.si), si_rdcache),
++ offsetof(typeof(*u.si), si_dirwh),
++ offsetof(typeof(*u.si), si_plink_lock),
++ offsetof(typeof(*u.si), si_plink),
++ offsetof(typeof(*u.si), si_kobj),
++ sizeof(*u.si));
++ printk("destr{len %d, name %d} %d\n",
++ offsetof(typeof(*u.destr), len),
++ offsetof(typeof(*u.destr), name),
++ sizeof(*u.destr));
++ printk("de{ino %d, type %d, str %d} %d\n",
++ offsetof(typeof(*u.de), de_ino),
++ offsetof(typeof(*u.de), de_type),
++ offsetof(typeof(*u.de), de_str),
++ sizeof(*u.de));
++ printk("wh{hash %d, bindex %d, str %d} %d\n",
++ offsetof(typeof(*u.wh), wh_hash),
++ offsetof(typeof(*u.wh), wh_bindex),
++ offsetof(typeof(*u.wh), wh_str),
++ sizeof(*u.wh));
++ printk("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n",
++ offsetof(typeof(*u.vd), vd_deblk),
++ offsetof(typeof(*u.vd), vd_nblk),
++ offsetof(typeof(*u.vd), vd_last),
++ offsetof(typeof(*u.vd), vd_version),
++ offsetof(typeof(*u.vd), vd_jiffy),
++ sizeof(*u.vd));
++ }
++#endif
++#endif
++
++ p = au_esc_chars;
++ for (i = 1; i <= ' '; i++)
++ *p++ = i;
++ *p++ = '\\';
++ *p++ = '\x7f';
++ *p = 0;
++
++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
++#ifndef CONFIG_AUFS_SYSAUFS
++ sysaufs_brs = 0;
++#endif
++
++ err = -EINVAL;
++ if (unlikely(aufs_nwkq <= 0))
++ goto out;
++ err = create_cache();
++ if (unlikely(err))
++ goto out;
++ err = sysaufs_init();
++ if (unlikely(err))
++ goto out_cache;
++ err = au_wkq_init();
++ if (unlikely(err))
++ goto out_kobj;
++ err = au_inotify_init();
++ if (unlikely(err))
++ goto out_wkq;
++ err = dbg_dlgt_init();
++ if (unlikely(err))
++ goto out_inotify;
++ err = register_filesystem(&aufs_fs_type);
++ if (unlikely(err))
++ goto out_dlgt;
++ printk(AUFS_NAME " " AUFS_VERSION "\n");
++ return 0; /* success */
++
++ out_dlgt:
++ dbg_dlgt_fin();
++ out_inotify:
++ au_inotify_fin();
++ out_wkq:
++ au_wkq_fin();
++ out_kobj:
++ sysaufs_fin();
++ out_cache:
++ destroy_cache();
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static void __exit aufs_exit(void)
++{
++ unregister_filesystem(&aufs_fs_type);
++ dbg_dlgt_fin();
++ au_inotify_fin();
++ au_wkq_fin();
++ sysaufs_fin();
++ destroy_cache();
++}
++
++module_init(aufs_init);
++module_exit(aufs_exit);
++
++/* ---------------------------------------------------------------------- */
++
++// fake Kconfig
++#if 1
++#ifdef CONFIG_AUFS_HINOTIFY
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_HINOTIFY is supported in linux-2.6.18 and later.
++#endif
++#ifndef CONFIG_INOTIFY
++#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
++#endif
++#endif
++
++#if AUFS_BRANCH_MAX > 511 && BITS_PER_LONG == 64 && PAGE_SIZE == 4096
++#warning For 4k pagesize and 64bit environment, \
++ CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
++#endif
++
++#ifdef CONFIG_AUFS_SYSAUFS
++#ifndef CONFIG_SYSFS
++#error CONFIG_AUFS_SYSAUFS requires CONFIG_SYSFS.
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_SYSAUFS requires linux-2.6.18 and later.
++#endif
++#endif
++
++#ifdef CONFIG_AUFS_EXPORT
++#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
++#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_EXPORT requires linux-2.6.18 and later.
++#endif
++#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
++#error need CONFIG_EXPORTFS=y to link aufs statically with CONFIG_AUFS_EXPORT
++#endif
++#endif
++
++#ifdef CONFIG_DEBUG_PROVE_LOCKING
++#if MAX_LOCKDEP_SUBCLASSES < AuLsc_End
++#warning lockdep will not work since aufs uses deeper locks.
++#endif
++#endif
++
++#ifdef CONFIG_AUFS_COMPAT
++#warning CONFIG_AUFS_COMPAT will be removed in the near future.
++#endif
++
++#endif
+diff --git a/fs/aufs/module.h b/fs/aufs/module.h
+new file mode 100755
+index 0000000..3769861
+--- /dev/null
++++ b/fs/aufs/module.h
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: module.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_MODULE_H__
++#define __AUFS_MODULE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/slab.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* module parameters */
++extern short aufs_nwkq;
++extern int sysaufs_brs;
++
++/* ---------------------------------------------------------------------- */
++
++extern char au_esc_chars[];
++extern int au_dir_roflags;
++
++/* kmem cache */
++enum {AuCache_DINFO, AuCache_ICNTNR, AuCache_FINFO, AuCache_VDIR,
++ AuCache_DEHSTR, AuCache_HINOTIFY, AuCache_Last};
++extern struct kmem_cache *aufs_cachep[];
++
++#define CacheFuncs(name, index) \
++static inline void *cache_alloc_##name(void) \
++{return kmem_cache_alloc(aufs_cachep[index], GFP_KERNEL);} \
++static inline void cache_free_##name(void *p) \
++{kmem_cache_free(aufs_cachep[index], p);}
++
++CacheFuncs(dinfo, AuCache_DINFO);
++CacheFuncs(icntnr, AuCache_ICNTNR);
++CacheFuncs(finfo, AuCache_FINFO);
++CacheFuncs(vdir, AuCache_VDIR);
++CacheFuncs(dehstr, AuCache_DEHSTR);
++CacheFuncs(hinotify, AuCache_HINOTIFY);
++
++#undef CacheFuncs
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MODULE_H__ */
+diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c
+new file mode 100755
+index 0000000..c1a9445
+--- /dev/null
++++ b/fs/aufs/opts.c
+@@ -0,0 +1,1043 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: opts.c,v 1.34 2007/05/14 03:40:27 sfjro Exp $ */
++
++#include <asm/types.h> // a distribution requires
++#include <linux/parser.h>
++#include "aufs.h"
++
++enum {
++ Opt_br,
++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
++ Opt_idel, Opt_imod,
++ Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash,
++ Opt_xino, Opt_zxino, Opt_noxino,
++ Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
++ Opt_udba,
++ Opt_diropq_a, Opt_diropq_w,
++ Opt_warn_perm, Opt_nowarn_perm,
++ Opt_findrw_dir, Opt_findrw_br,
++ Opt_coo,
++ Opt_dlgt, Opt_nodlgt,
++ Opt_tail, Opt_ignore, Opt_err
++};
++
++static match_table_t options = {
++ {Opt_br, "br=%s"},
++ {Opt_br, "br:%s"},
++
++ {Opt_add, "add=%d:%s"},
++ {Opt_add, "add:%d:%s"},
++ {Opt_add, "ins=%d:%s"},
++ {Opt_add, "ins:%d:%s"},
++ {Opt_append, "append=%s"},
++ {Opt_append, "append:%s"},
++ {Opt_prepend, "prepend=%s"},
++ {Opt_prepend, "prepend:%s"},
++
++ {Opt_del, "del=%s"},
++ {Opt_del, "del:%s"},
++ //{Opt_idel, "idel:%d"},
++ {Opt_mod, "mod=%s"},
++ {Opt_mod, "mod:%s"},
++ //{Opt_imod, "imod:%d:%s"},
++
++ {Opt_dirwh, "dirwh=%d"},
++ {Opt_dirwh, "dirwh:%d"},
++
++ {Opt_xino, "xino=%s"},
++ {Opt_xino, "xino:%s"},
++ {Opt_noxino, "noxino"},
++ //{Opt_zxino, "zxino=%s"},
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ {Opt_plink, "plink"},
++ {Opt_noplink, "noplink"},
++#ifdef CONFIG_AUFS_DEBUG
++ {Opt_list_plink, "list_plink"},
++#endif
++ {Opt_clean_plink, "clean_plink"},
++#endif
++
++ {Opt_udba, "udba=%s"},
++
++ {Opt_diropq_a, "diropq=always"},
++ {Opt_diropq_a, "diropq=a"},
++ {Opt_diropq_w, "diropq=whiteouted"},
++ {Opt_diropq_w, "diropq=w"},
++
++ {Opt_warn_perm, "warn_perm"},
++ {Opt_nowarn_perm, "nowarn_perm"},
++
++#ifdef CONFIG_AUFS_DLGT
++ {Opt_dlgt, "dlgt"},
++ {Opt_nodlgt, "nodlgt"},
++#endif
++
++ {Opt_rdcache, "rdcache=%d"},
++ {Opt_rdcache, "rdcache:%d"},
++#if 0
++ {Opt_findrw_dir, "findrw=dir"},
++ {Opt_findrw_br, "findrw=br"},
++
++ {Opt_coo, "coo=%s"},
++
++ {Opt_deblk, "deblk=%d"},
++ {Opt_deblk, "deblk:%d"},
++ {Opt_nhash, "nhash=%d"},
++ {Opt_nhash, "nhash:%d"},
++#endif
++
++ {Opt_br, "dirs=%s"},
++ {Opt_ignore, "debug=%d"},
++ {Opt_ignore, "delete=whiteout"},
++ {Opt_ignore, "delete=all"},
++ {Opt_ignore, "imap=%s"},
++
++ {Opt_err, NULL}
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define RW "rw"
++#define RO "ro"
++#define WH "wh"
++#define RR "rr"
++#define NoLinkWH "nolwh"
++
++static match_table_t brperms = {
++ {AuBr_RR, RR},
++ {AuBr_RO, RO},
++ {AuBr_RW, RW},
++
++ {AuBr_RRWH, RR "+" WH},
++ {AuBr_ROWH, RO "+" WH},
++ {AuBr_RWNoLinkWH, RW "+" NoLinkWH},
++
++ {AuBr_ROWH, "nfsro"},
++ {AuBr_RO, NULL}
++};
++
++static int br_perm_val(char *perm)
++{
++ int val;
++ substring_t args[MAX_OPT_ARGS];
++
++ DEBUG_ON(!perm || !*perm);
++ LKTRTrace("perm %s\n", perm);
++ val = match_token(perm, brperms, args);
++ TraceErr(val);
++ return val;
++}
++
++int br_perm_str(char *p, unsigned int len, int brperm)
++{
++ struct match_token *bp = brperms;
++
++ LKTRTrace("len %d, 0x%x\n", len, brperm);
++
++ while (bp->pattern) {
++ if (bp->token == brperm) {
++ if (strlen(bp->pattern) < len) {
++ strcpy(p, bp->pattern);
++ return 0;
++ } else
++ return -E2BIG;
++ }
++ bp++;
++ }
++
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t udbalevel = {
++ {AuFlag_UDBA_REVAL, "reval"},
++#ifdef CONFIG_AUFS_HINOTIFY
++ {AuFlag_UDBA_INOTIFY, "inotify"},
++#endif
++ {AuFlag_UDBA_NONE, "none"},
++ {-1, NULL}
++};
++
++static int udba_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++ return match_token(str, udbalevel, args);
++}
++
++au_parser_pattern_t udba_str(int udba)
++{
++ struct match_token *p = udbalevel;
++ while (p->pattern) {
++ if (p->token == udba)
++ return p->pattern;
++ p++;
++ }
++ BUG();
++ return "??";
++}
++
++void udba_set(struct super_block *sb, unsigned int flg)
++{
++ au_flag_clr(sb, AuMask_UDBA);
++ au_flag_set(sb, flg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t coolevel = {
++ {AuFlag_COO_LEAF, "leaf"},
++ {AuFlag_COO_ALL, "all"},
++ {AuFlag_COO_NONE, "none"},
++ {-1, NULL}
++};
++
++#if 0
++static int coo_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++ return match_token(str, coolevel, args);
++}
++#endif
++
++au_parser_pattern_t coo_str(int coo)
++{
++ struct match_token *p = coolevel;
++ while (p->pattern) {
++ if (p->token == coo)
++ return p->pattern;
++ p++;
++ }
++ BUG();
++ return "??";
++}
++static void coo_set(struct super_block *sb, unsigned int flg)
++{
++ au_flag_clr(sb, AuMask_COO);
++ au_flag_set(sb, flg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
++
++#ifdef CONFIG_AUFS_DEBUG
++static void dump_opts(struct opts *opts)
++{
++ /* reduce stack space */
++ union {
++ struct opt_add *add;
++ struct opt_del *del;
++ struct opt_mod *mod;
++ struct opt_xino *xino;
++ } u;
++ struct opt *opt;
++
++ TraceEnter();
++
++ opt = opts->opt;
++ while (/* opt < opts_tail && */ opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ u.add = &opt->add;
++ LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ u.del = &opt->del;
++ LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ u.mod = &opt->mod;
++ LKTRTrace("mod {%s, 0x%x, %p}\n",
++ u.mod->path, u.mod->perm, u.mod->h_root);
++ break;
++ case Opt_append:
++ u.add = &opt->add;
++ LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_prepend:
++ u.add = &opt->add;
++ LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_dirwh:
++ LKTRTrace("dirwh %d\n", opt->dirwh);
++ break;
++ case Opt_rdcache:
++ LKTRTrace("rdcache %d\n", opt->rdcache);
++ break;
++ case Opt_xino:
++ u.xino = &opt->xino;
++ LKTRTrace("xino {%s %.*s}\n",
++ u.xino->path, DLNPair(u.xino->file->f_dentry));
++ break;
++ case Opt_noxino:
++ LKTRLabel(noxino);
++ break;
++ case Opt_plink:
++ LKTRLabel(plink);
++ break;
++ case Opt_noplink:
++ LKTRLabel(noplink);
++ break;
++ case Opt_list_plink:
++ LKTRLabel(list_plink);
++ break;
++ case Opt_clean_plink:
++ LKTRLabel(clean_plink);
++ break;
++ case Opt_udba:
++ LKTRTrace("udba %d, %s\n",
++ opt->udba, udba_str(opt->udba));
++ break;
++ case Opt_diropq_a:
++ LKTRLabel(diropq_a);
++ break;
++ case Opt_diropq_w:
++ LKTRLabel(diropq_w);
++ break;
++ case Opt_warn_perm:
++ LKTRLabel(warn_perm);
++ break;
++ case Opt_nowarn_perm:
++ LKTRLabel(nowarn_perm);
++ break;
++ case Opt_dlgt:
++ LKTRLabel(dlgt);
++ break;
++ case Opt_nodlgt:
++ LKTRLabel(nodlgt);
++ break;
++ case Opt_coo:
++ LKTRTrace("coo %d, %s\n", opt->coo, coo_str(opt->coo));
++ break;
++ default:
++ BUG();
++ }
++ opt++;
++ }
++}
++#else
++#define dump_opts(opts) /* */
++#endif
++
++void au_free_opts(struct opts *opts)
++{
++ struct opt *opt;
++
++ TraceEnter();
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ case Opt_append:
++ case Opt_prepend:
++ path_release(&opt->add.nd);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ dput(opt->del.h_root);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ dput(opt->mod.h_root);
++ break;
++ case Opt_xino:
++ fput(opt->xino.file);
++ break;
++ }
++ opt++;
++ }
++}
++
++static int opt_add(struct opt *opt, char *opt_str, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct opt_add *add = &opt->add;
++ char *p;
++
++ LKTRTrace("%s, b%d\n", opt_str, bindex);
++
++ add->bindex = bindex;
++ add->perm = AuBr_RO;
++ if (!bindex && !(sb->s_flags & MS_RDONLY))
++ add->perm = AuBr_RW;
++#ifdef CONFIG_AUFS_COMPAT
++ add->perm = AuBr_RW;
++#endif
++ add->path = opt_str;
++ p = strchr(opt_str, '=');
++ if (unlikely(p)) {
++ *p++ = 0;
++ if (*p)
++ add->perm = br_perm_val(p);
++ }
++
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(add->path, lkup_dirflags, &add->nd);
++ //err = -1;
++ if (!err) {
++ opt->type = Opt_add;
++ goto out;
++ }
++ Err("lookup failed %s (%d)\n", add->path, err);
++ err = -EINVAL;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* called without aufs lock */
++int au_parse_opts(struct super_block *sb, char *str, struct opts *opts)
++{
++ int err, n;
++ struct dentry *root;
++ struct opt *opt, *opt_tail;
++ char *opt_str;
++ substring_t args[MAX_OPT_ARGS];
++ aufs_bindex_t bindex;
++ struct nameidata nd;
++ /* reduce stack space */
++ union {
++ struct opt_del *del;
++ struct opt_mod *mod;
++ struct opt_xino *xino;
++ } u;
++ struct file *file;
++
++ LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
++
++ root = sb->s_root;
++ err = 0;
++ bindex = 0;
++ opt = opts->opt;
++ opt_tail = opt + opts->max_opt - 1;
++ opt->type = Opt_tail;
++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
++ int token, skipped;
++ char *p;
++ err = -EINVAL;
++ token = match_token(opt_str, options, args);
++ LKTRTrace("%s, token %d, args[0]{%p, %p}\n",
++ opt_str, token, args[0].from, args[0].to);
++
++ skipped = 0;
++ switch (token) {
++ case Opt_br:
++ err = 0;
++ while (!err && (opt_str = strsep(&args[0].from, ":"))
++ && *opt_str) {
++ err = opt_add(opt, opt_str, sb, bindex++);
++ //if (LktrCond) err = -1;
++ if (unlikely(!err && ++opt > opt_tail)) {
++ err = -E2BIG;
++ break;
++ }
++ opt->type = Opt_tail;
++ skipped = 1;
++ }
++ break;
++ case Opt_add:
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ err = opt_add(opt, args[1].from, sb, bindex);
++ break;
++ case Opt_append:
++ case Opt_prepend:
++ err = opt_add(opt, args[0].from, sb, /*dummy bindex*/1);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_del:
++ u.del = &opt->del;
++ u.del->path = args[0].from;
++ LKTRTrace("del path %s\n", u.del->path);
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(u.del->path, lkup_dirflags, &nd);
++ if (unlikely(err)) {
++ Err("lookup failed %s (%d)\n", u.del->path, err);
++ break;
++ }
++ u.del->h_root = dget(nd.dentry);
++ path_release(&nd);
++ opt->type = token;
++ break;
++#if 0
++ case Opt_idel:
++ u.del = &opt->del;
++ u.del->path = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (bindex < 0 || sbend(sb) < bindex) {
++ Err("out of bounds, %d\n", bindex);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++ }
++ err = 0;
++ u.del->h_root = dget(au_h_dptr_i(root, bindex));
++ opt->type = token;
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++#endif
++
++ case Opt_mod:
++ u.mod = &opt->mod;
++ u.mod->path = args[0].from;
++ p = strchr(u.mod->path, '=');
++ if (unlikely(!p)) {
++ Err("no permssion %s\n", opt_str);
++ break;
++ }
++ *p++ = 0;
++ u.mod->perm = br_perm_val(p);
++ LKTRTrace("mod path %s, perm 0x%x, %s\n",
++ u.mod->path, u.mod->perm, p);
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(u.mod->path, lkup_dirflags, &nd);
++ if (unlikely(err)) {
++ Err("lookup failed %s (%d)\n", u.mod->path, err);
++ break;
++ }
++ u.mod->h_root = dget(nd.dentry);
++ path_release(&nd);
++ opt->type = token;
++ break;
++#if 0
++ case Opt_imod:
++ u.mod = &opt->mod;
++ u.mod->path = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (bindex < 0 || sbend(sb) < bindex) {
++ Err("out of bounds, %d\n", bindex);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++ }
++ u.mod->perm = br_perm_val(args[1].from);
++ LKTRTrace("mod path %s, perm 0x%x, %s\n",
++ u.mod->path, u.mod->perm, args[1].from);
++ err = 0;
++ u.mod->h_root = dget(au_h_dptr_i(root, bindex));
++ opt->type = token;
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++#endif
++ case Opt_xino:
++ u.xino = &opt->xino;
++ file = xino_create(sb, args[0].from, /*silent*/0,
++ /*parent*/NULL);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ break;
++ err = -EINVAL;
++ if (unlikely(file->f_dentry->d_sb == sb)) {
++ fput(file);
++ Err("%s must be outside\n", args[0].from);
++ break;
++ }
++ err = 0;
++ u.xino->file = file;
++ u.xino->path = args[0].from;
++ opt->type = token;
++ break;
++
++ case Opt_dirwh:
++ if (unlikely(match_int(&args[0], &opt->dirwh)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_rdcache:
++ if (unlikely(match_int(&args[0], &opt->rdcache)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_noxino:
++ case Opt_plink:
++ case Opt_noplink:
++ case Opt_list_plink:
++ case Opt_clean_plink:
++ case Opt_diropq_a:
++ case Opt_diropq_w:
++ case Opt_warn_perm:
++ case Opt_nowarn_perm:
++ case Opt_dlgt:
++ case Opt_nodlgt:
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_udba:
++ opt->udba = udba_val(args[0].from);
++ if (opt->udba >= 0) {
++ err = 0;
++ opt->type = token;
++ }
++ break;
++
++#if 0
++ case Opt_coo:
++ opt->coo = coo_val(args[0].from);
++ if (opt->coo >= 0) {
++ err = 0;
++ opt->type = token;
++ }
++ break;
++#endif
++
++ case Opt_ignore:
++#ifndef CONFIG_AUFS_COMPAT
++ Warn("ignored %s\n", opt_str);
++#endif
++ skipped = 1;
++ err = 0;
++ break;
++ case Opt_err:
++ Err("unknown option %s\n", opt_str);
++ break;
++ }
++
++ if (!err && !skipped) {
++ if (unlikely(++opt > opt_tail)) {
++ err = -E2BIG;
++ opt--;
++ opt->type = Opt_tail;
++ break;
++ }
++ opt->type = Opt_tail;
++ }
++ }
++
++ dump_opts(opts);
++ if (unlikely(err))
++ au_free_opts(opts);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns,
++ * plus: processed without an error
++ * zero: unprocessed
++ */
++static int au_do_opt_simple(struct super_block *sb, struct opt *opt,
++ int remount, unsigned int *given)
++{
++ int err;
++ struct aufs_sbinfo *sbinfo = stosi(sb);
++
++ TraceEnter();
++
++ err = 1; /* handled */
++ switch (opt->type) {
++ case Opt_udba:
++ udba_set(sb, opt->udba);
++ *given |= opt->udba;
++ break;
++
++ case Opt_plink:
++ au_flag_set(sb, AuFlag_PLINK);
++ *given |= AuFlag_PLINK;
++ break;
++ case Opt_noplink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_put_plink(sb);
++ au_flag_clr(sb, AuFlag_PLINK);
++ *given |= AuFlag_PLINK;
++ break;
++ case Opt_list_plink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_list_plink(sb);
++ break;
++ case Opt_clean_plink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_put_plink(sb);
++ break;
++
++ case Opt_diropq_a:
++ au_flag_set(sb, AuFlag_ALWAYS_DIROPQ);
++ *given |= AuFlag_ALWAYS_DIROPQ;
++ break;
++ case Opt_diropq_w:
++ au_flag_clr(sb, AuFlag_ALWAYS_DIROPQ);
++ *given |= AuFlag_ALWAYS_DIROPQ;
++ break;
++
++ case Opt_dlgt:
++ au_flag_set(sb, AuFlag_DLGT);
++ *given |= AuFlag_DLGT;
++ break;
++ case Opt_nodlgt:
++ au_flag_clr(sb, AuFlag_DLGT);
++ *given |= AuFlag_DLGT;
++ break;
++
++ case Opt_warn_perm:
++ au_flag_set(sb, AuFlag_WARN_PERM);
++ *given |= AuFlag_WARN_PERM;
++ break;
++ case Opt_nowarn_perm:
++ au_flag_clr(sb, AuFlag_WARN_PERM);
++ *given |= AuFlag_WARN_PERM;
++ break;
++
++ case Opt_coo:
++ coo_set(sb, opt->coo);
++ *given |= opt->coo;
++ break;
++
++ case Opt_dirwh:
++ sbinfo->si_dirwh = opt->dirwh;
++ break;
++
++ case Opt_rdcache:
++ sbinfo->si_rdcache = opt->rdcache * HZ;
++ break;
++
++ default:
++ err = 0;
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns tri-state.
++ * plus: processed without an error
++ * zero: unprocessed
++ * minus: error
++ */
++static int au_do_opt_br(struct super_block *sb, struct opt *opt, int remount,
++ int *do_refresh)
++{
++ int err;
++
++ TraceEnter();
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_append:
++ opt->add.bindex = sbend(sb) + 1;
++ goto add;
++ case Opt_prepend:
++ opt->add.bindex = 0;
++ add:
++ case Opt_add:
++ err = br_add(sb, &opt->add, remount);
++ if (!err)
++ *do_refresh = err = 1;
++ break;
++
++ case Opt_del:
++ case Opt_idel:
++ err = br_del(sb, &opt->del, remount);
++ if (!err)
++ *do_refresh = err = 1;
++ break;
++
++ case Opt_mod:
++ case Opt_imod:
++ err = br_mod(sb, &opt->mod, remount, do_refresh);
++ if (!err)
++ err = 1;
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int au_do_opt_xino(struct super_block *sb, struct opt *opt, int remount,
++ struct opt_xino **opt_xino)
++{
++ int err;
++
++ TraceEnter();
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_xino:
++ err = xino_set(sb, &opt->xino, remount);
++ if (!err)
++ *opt_xino = &opt->xino;
++ break;
++ case Opt_noxino:
++ err = xino_clr(sb);
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int verify_opts(struct super_block *sb, int remount)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct aufs_branch *br;
++ struct dentry *root;
++ struct inode *dir;
++ unsigned int do_plink;
++
++ TraceEnter();
++
++ if (unlikely(!(sb->s_flags & MS_RDONLY)
++ && !br_writable(sbr_perm(sb, 0))))
++ Warn("first branch should be rw\n");
++
++ err = 0;
++ root = sb->s_root;
++ dir = sb->s_root->d_inode;
++ do_plink = au_flag_test(sb, AuFlag_PLINK);
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ struct inode *h_dir;
++ int skip;
++
++ skip = 0;
++ h_dir = au_h_iptr_i(dir, bindex);
++ br = stobr(sb, bindex);
++ br_wh_read_lock(br);
++ switch (br->br_perm) {
++ case AuBr_RR:
++ case AuBr_RO:
++ case AuBr_RRWH:
++ case AuBr_ROWH:
++ skip = (!br->br_wh && !br->br_plink);
++ break;
++
++ case AuBr_RWNoLinkWH:
++ skip = !br->br_wh;
++ if (skip) {
++ if (do_plink)
++ skip = !!br->br_plink;
++ else
++ skip = !br->br_plink;
++ }
++ break;
++
++ case AuBr_RW:
++ skip = !!br->br_wh;
++ if (skip) {
++ if (do_plink)
++ skip = !!br->br_plink;
++ else
++ skip = !br->br_plink;
++ }
++ break;
++
++ default:
++ BUG();
++ }
++ br_wh_read_unlock(br);
++
++ if (skip)
++ continue;
++
++ hdir_lock(h_dir, dir, bindex);
++ br_wh_write_lock(br);
++ err = init_wh(au_h_dptr_i(root, bindex), br,
++ au_nfsmnt(sb, bindex), sb);
++ br_wh_write_unlock(br);
++ hdir_unlock(h_dir, dir, bindex);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++int au_do_opts_mount(struct super_block *sb, struct opts *opts)
++{
++ int err, do_refresh;
++ struct inode *dir;
++ struct opt *opt;
++ unsigned int flags, given;
++ struct opt_xino *opt_xino;
++ aufs_bindex_t bend, bindex;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DiMustWriteLock(sb->s_root);
++ dir = sb->s_root->d_inode;
++ IiMustWriteLock(dir);
++
++ err = 0;
++ given = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_do_opt_simple(sb, opt++, /*remount*/0, &given);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ /* disable them temporary */
++ flags = au_flag_test(sb, AuFlag_XINO | AuMask_UDBA | AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_XINO | AuFlag_DLGT);
++ udba_set(sb, AuFlag_UDBA_REVAL);
++
++ do_refresh = 0;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ bend = sbend(sb);
++ if (unlikely(bend < 0)) {
++ err = -EINVAL;
++ Err("no branches\n");
++ goto out;
++ }
++
++ if (flags & AuFlag_XINO)
++ au_flag_set(sb, AuFlag_XINO);
++ opt = opts->opt;
++ while (!err && opt->type != Opt_tail)
++ err = au_do_opt_xino(sb, opt++, /*remount*/0, &opt_xino);
++ if (unlikely(err))
++ goto out;
++
++ //todo: test this error case.
++ err = verify_opts(sb, /*remount*/0);
++ DEBUG_ON(err);
++ if (unlikely(err))
++ goto out;
++
++ /* enable xino */
++ if (au_flag_test(sb, AuFlag_XINO) && !opt_xino) {
++ struct file *xino_file = xino_def(sb);
++ err = PTR_ERR(xino_file);
++ if (IS_ERR(xino_file))
++ goto out;
++
++ err = 0;
++ for (bindex = 0; !err && bindex <= bend; bindex++)
++ err = xino_init(sb, bindex, xino_file,
++ /*do_test*/bindex);
++ fput(xino_file);
++ if (unlikely(err))
++ goto out;
++ }
++
++ /* restore hinotify */
++ udba_set(sb, flags & AuMask_UDBA);
++ if (flags & AuFlag_UDBA_INOTIFY)
++ au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AUFS_HI_XINO);
++
++ /* restore dlgt */
++ if (flags & AuFlag_DLGT)
++ au_flag_set(sb, AuFlag_DLGT);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int au_do_opts_remount(struct super_block *sb, struct opts *opts,
++ int *do_refresh, unsigned int *given)
++{
++ int err, rerr;
++ struct inode *dir;
++ struct opt_xino *opt_xino;
++ struct opt *opt;
++ unsigned int dlgt;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DiMustWriteLock(sb->s_root);
++ dir = sb->s_root->d_inode;
++ IiMustWriteLock(dir);
++ //DEBUG_ON(au_flag_test(sb, AuFlag_UDBA_INOTIFY));
++
++ err = 0;
++ *do_refresh = 0;
++ *given = 0;
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail) {
++ err = au_do_opt_simple(sb, opt, /*remount*/1, given);
++
++ /* disable it temporary */
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_DLGT);
++
++ if (!err)
++ err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh);
++ if (!err)
++ err = au_do_opt_xino(sb, opt, /*remount*/1, &opt_xino);
++
++ /* restore it */
++ au_flag_set(sb, dlgt);
++ opt++;
++ }
++ if (err > 0)
++ err = 0;
++ TraceErr(err);
++
++ /* go on if err */
++
++ //todo: test this error case.
++ au_flag_clr(sb, AuFlag_DLGT);
++ rerr = verify_opts(sb, /*remount*/1);
++ au_flag_set(sb, dlgt);
++
++ /* they are handled by the caller */
++ if (!*do_refresh)
++ *do_refresh = !!((*given & AuMask_UDBA)
++ || au_flag_test(sb, AuFlag_XINO));
++
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h
+new file mode 100755
+index 0000000..16c1a6a
+--- /dev/null
++++ b/fs/aufs/opts.h
+@@ -0,0 +1,96 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: opts.h,v 1.13 2007/05/14 06:27:18 sfjro Exp $ */
++
++#ifndef __AUFS_OPTS_H__
++#define __AUFS_OPTS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++typedef const char* au_parser_pattern_t;
++#else
++typedef char* au_parser_pattern_t;
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct opt_add {
++ aufs_bindex_t bindex;
++ char *path;
++ int perm;
++ struct nameidata nd;
++};
++
++struct opt_del {
++ char *path;
++ struct dentry *h_root;
++};
++
++struct opt_mod {
++ char *path;
++ int perm;
++ struct dentry *h_root;
++};
++
++struct opt_xino {
++ char *path;
++ struct file *file;
++};
++
++struct opt {
++ int type;
++ union {
++ struct opt_xino xino;
++ struct opt_add add;
++ struct opt_del del;
++ struct opt_mod mod;
++ int dirwh;
++ int rdcache;
++ int deblk;
++ int nhash;
++ int udba;
++ int coo;
++ };
++};
++
++struct opts {
++ struct opt *opt;
++ int max_opt;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int br_perm_str(char *p, unsigned int len, int brperm);
++au_parser_pattern_t udba_str(int udba);
++void udba_set(struct super_block *sb, unsigned int flg);
++//au_parser_pattern_t coo_str(int coo);
++void au_free_opts(struct opts *opts);
++int au_parse_opts(struct super_block *sb, char *str, struct opts *opts);
++int au_do_opts_mount(struct super_block *sb, struct opts *opts);
++int au_do_opts_remount(struct super_block *sb, struct opts *opts,
++ int *do_refresh, unsigned int *given);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_OPTS_H__ */
+diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c
+new file mode 100755
+index 0000000..0e520af
+--- /dev/null
++++ b/fs/aufs/plink.c
+@@ -0,0 +1,331 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: plink.c,v 1.4 2007/05/14 03:39:10 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct pseudo_link {
++ struct list_head list;
++ struct inode *inode;
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++void au_list_plink(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ TraceEnter();
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list)
++ Dbg("%lu\n", plink->inode->i_ino);
++ spin_unlock(&sbinfo->si_plink_lock);
++}
++#endif
++
++int au_is_plinked(struct super_block *sb, struct inode *inode)
++{
++ int found;
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ found = 0;
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list)
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ spin_unlock(&sbinfo->si_plink_lock);
++ return found;
++}
++
++// 20 is max digits length of ulong 64
++#define PLINK_NAME_LEN ((20 + 1) * 2)
++
++static int plink_name(char *name, int len, struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ int rlen;
++ struct inode *h_inode;
++
++ LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
++ DEBUG_ON(len != PLINK_NAME_LEN);
++ h_inode = au_h_iptr_i(inode, bindex);
++ DEBUG_ON(!h_inode);
++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
++ DEBUG_ON(rlen >= len);
++ return rlen;
++}
++
++struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode)
++{
++ struct dentry *h_dentry, *h_parent;
++ struct aufs_branch *br;
++ struct inode *h_dir;
++ char tgtname[PLINK_NAME_LEN];
++ int len;
++ struct lkup_args lkup;
++
++ LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
++ br = stobr(sb, bindex);
++ h_parent = br->br_plink;
++ DEBUG_ON(!h_parent);
++ h_dir = h_parent->d_inode;
++ DEBUG_ON(!h_dir);
++
++ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
++
++ // always superio.
++ lkup.nfsmnt = au_do_nfsmnt(br->br_mnt);
++ lkup.dlgt = need_dlgt(sb);
++ hi_lock_whplink(h_dir);
++ h_dentry = sio_lkup_one(tgtname, h_parent, len, &lkup);
++ i_unlock(h_dir);
++ return h_dentry;
++}
++
++static int do_whplink(char *tgt, int len, struct dentry *h_parent,
++ struct dentry *h_dentry, struct vfsmount *nfsmnt,
++ struct super_block *sb)
++{
++ int err;
++ struct dentry *h_tgt;
++ struct inode *h_dir;
++ struct lkup_args lkup = {
++ .nfsmnt = nfsmnt,
++ .dlgt = need_dlgt(sb)
++ };
++
++ h_tgt = lkup_one(tgt, h_parent, len, &lkup);
++ err = PTR_ERR(h_tgt);
++ if (IS_ERR(h_tgt))
++ goto out;
++
++ err = 0;
++ h_dir = h_parent->d_inode;
++ if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode))
++ err = vfsub_unlink(h_dir, h_tgt, lkup.dlgt);
++ if (!err && !h_tgt->d_inode) {
++ err = vfsub_link(h_dentry, h_dir, h_tgt, lkup.dlgt);
++ //inode->i_nlink++;
++ }
++ dput(h_tgt);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct do_whplink_args {
++ int *errp;
++ char *tgt;
++ int len;
++ struct dentry *h_parent;
++ struct dentry *h_dentry;
++ struct vfsmount *nfsmnt;
++ struct super_block *sb;
++};
++
++static void call_do_whplink(void *args)
++{
++ struct do_whplink_args *a = args;
++ *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
++ a->nfsmnt, a->sb);
++}
++
++static int whplink(struct dentry *h_dentry, struct inode *inode,
++ aufs_bindex_t bindex, struct super_block *sb)
++{
++ int err, len;
++ struct aufs_branch *br;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ char tgtname[PLINK_NAME_LEN];
++
++ LKTRTrace("%.*s\n", DLNPair(h_dentry));
++ br = stobr(inode->i_sb, bindex);
++ h_parent = br->br_plink;
++ DEBUG_ON(!h_parent);
++ h_dir = h_parent->d_inode;
++ DEBUG_ON(!h_dir);
++
++ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
++
++ // always superio.
++ hi_lock_whplink(h_dir);
++ if (!is_au_wkq(current)) {
++ struct do_whplink_args args = {
++ .errp = &err,
++ .tgt = tgtname,
++ .len = len,
++ .h_parent = h_parent,
++ .h_dentry = h_dentry,
++ .nfsmnt = au_do_nfsmnt(br->br_mnt),
++ .sb = sb
++ };
++ au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
++ } else
++ err = do_whplink(tgtname, len, h_parent, h_dentry,
++ au_do_nfsmnt(br->br_mnt), sb);
++ i_unlock(h_dir);
++
++ TraceErr(err);
++ return err;
++}
++
++void append_plink(struct super_block *sb, struct inode *inode,
++ struct dentry *h_dentry, aufs_bindex_t bindex)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++ int found, err, cnt;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ cnt = 0;
++ found = 0;
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list) {
++ cnt++;
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ }
++
++ err = 0;
++ if (!found) {
++ struct pseudo_link *plink;
++
++ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
++ if (plink) {
++ plink->inode = igrab(inode);
++ list_add(&plink->list, plink_list);
++ cnt++;
++ } else
++ err = -ENOMEM;
++ }
++ spin_unlock(&sbinfo->si_plink_lock);
++
++ if (!err)
++ err = whplink(h_dentry, inode, bindex, sb);
++
++ if (unlikely(cnt > 100))
++ Warn1("unexpectedly many pseudo links, %d\n", cnt);
++ if (unlikely(err))
++ Warn("err %d, damaged pseudo link. ignored.\n", err);
++}
++
++static void do_put_plink(struct pseudo_link *plink, int do_del)
++{
++ TraceEnter();
++
++ iput(plink->inode);
++ if (do_del)
++ list_del(&plink->list);
++ kfree(plink);
++}
++
++void au_put_plink(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ //spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry_safe(plink, tmp, plink_list, list)
++ do_put_plink(plink, 0);
++ INIT_LIST_HEAD(plink_list);
++ //spin_unlock(&sbinfo->si_plink_lock);
++}
++
++void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++ struct inode *inode;
++ aufs_bindex_t bstart, bend, bindex;
++ int do_put;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ //spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry_safe(plink, tmp, plink_list, list) {
++ do_put = 0;
++ inode = igrab(plink->inode);
++ ii_write_lock_child(inode);
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (!au_h_iptr_i(inode, bindex)
++ || itoid_index(inode, bindex) != br_id)
++ continue;
++ set_h_iptr(inode, bindex, NULL, 0);
++ do_put = 1;
++ break;
++ }
++ } else
++ do_put_plink(plink, 1);
++
++ if (do_put) {
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (au_h_iptr_i(inode, bindex)) {
++ do_put = 0;
++ break;
++ }
++ if (do_put)
++ do_put_plink(plink, 1);
++ }
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++ //spin_unlock(&sbinfo->si_plink_lock);
++}
+diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
+new file mode 100755
+index 0000000..55cb64c
+--- /dev/null
++++ b/fs/aufs/sbinfo.c
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sbinfo.c,v 1.30 2007/05/14 03:39:31 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct aufs_sbinfo *stosi(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ sbinfo = sb->s_fs_info;
++ //DEBUG_ON(sbinfo->si_bend < 0);
++ return sbinfo;
++}
++
++aufs_bindex_t sbend(struct super_block *sb)
++{
++ SiMustAnyLock(sb);
++ return stosi(sb)->si_bend;
++}
++
++struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex)
++{
++ SiMustAnyLock(sb);
++ DEBUG_ON(bindex < 0 || sbend(sb) < bindex
++ || !stosi(sb)->si_branch[0 + bindex]);
++ return stosi(sb)->si_branch[0 + bindex];
++}
++
++int au_sigen(struct super_block *sb)
++{
++ SiMustAnyLock(sb);
++ return stosi(sb)->si_generation;
++}
++
++int au_sigen_inc(struct super_block *sb)
++{
++ int gen;
++
++ SiMustWriteLock(sb);
++ gen = ++stosi(sb)->si_generation;
++ au_update_digen(sb->s_root);
++ au_update_iigen(sb->s_root->d_inode);
++ sb->s_root->d_inode->i_version++;
++ return gen;
++}
++
++int find_bindex(struct super_block *sb, struct aufs_branch *br)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (stobr(sb, bindex) == br)
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry and super_block lock. call at entry point */
++void aufs_read_lock(struct dentry *dentry, int flags)
++{
++ si_read_lock(dentry->d_sb);
++ if (flags & AUFS_D_WLOCK)
++ di_write_lock_child(dentry);
++ else
++ di_read_lock_child(dentry, flags);
++}
++
++void aufs_read_unlock(struct dentry *dentry, int flags)
++{
++ if (flags & AUFS_D_WLOCK)
++ di_write_unlock(dentry);
++ else
++ di_read_unlock(dentry, flags);
++ si_read_unlock(dentry->d_sb);
++}
++
++void aufs_write_lock(struct dentry *dentry)
++{
++ //au_wkq_wait_nwtask();
++ si_write_lock(dentry->d_sb);
++ di_write_lock_child(dentry);
++}
++
++void aufs_write_unlock(struct dentry *dentry)
++{
++ di_write_unlock(dentry);
++ si_write_unlock(dentry->d_sb);
++ //au_wkq_wait_nwtask();
++}
++
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
++ si_read_lock(d1->d_sb);
++ di_write_lock2_child(d1, d2, isdir);
++}
++
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
++ di_write_unlock2(d1, d2);
++ si_read_unlock(d1->d_sb);
++}
++
++/* ---------------------------------------------------------------------- */
++
++aufs_bindex_t new_br_id(struct super_block *sb)
++{
++ aufs_bindex_t br_id;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++
++ while (1) {
++ br_id = ++stosi(sb)->si_last_br_id;
++ if (br_id && find_brindex(sb, br_id) < 0)
++ return br_id;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_SYSAUFS
++static int make_xino(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++ struct super_block *sb = args->sb;
++ aufs_bindex_t bindex, bend;
++ struct file *xf;
++ struct inode *xi;
++
++ TraceEnter();
++ DEBUG_ON(args->index != SysaufsSb_XINO);
++ SiMustReadLock(sb);
++
++ *do_size = 0;
++ err = seq_printf(seq, "%d %lu\n", sizeof(struct xino),
++ atomic_long_read(&stosi(sb)->si_xino));
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ xf = stobr(sb, bindex)->br_xino;
++ xi = xf->f_dentry->d_inode;
++ err = seq_printf(seq, "%d: %d, %Lux%d %Ld\n",
++ bindex, file_count(xf),
++ (u64)xi->i_blocks, 1 << xi->i_blkbits,
++ i_size_read(xi));
++ }
++ return err;
++}
++
++sysaufs_op au_si_ops[] = {
++ [SysaufsSb_XINO] = make_xino
++};
++#endif
+diff --git a/fs/aufs/super.c b/fs/aufs/super.c
+new file mode 100755
+index 0000000..c1123f8
+--- /dev/null
++++ b/fs/aufs/super.c
+@@ -0,0 +1,716 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: super.c,v 1.50 2007/05/14 03:39:42 sfjro Exp $ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/*
++ * super_operations
++ */
++static struct inode *aufs_alloc_inode(struct super_block *sb)
++{
++ struct aufs_icntnr *c;
++
++ TraceEnter();
++
++ c = cache_alloc_icntnr();
++ //if (LktrCond) {cache_free_icntnr(c); c = NULL;}
++ if (c) {
++ inode_init_once(&c->vfs_inode);
++ c->vfs_inode.i_version = 1; //sigen(sb);
++ c->iinfo.ii_hinode = NULL;
++ return &c->vfs_inode;
++ }
++ return NULL;
++}
++
++static void aufs_destroy_inode(struct inode *inode)
++{
++ LKTRTrace("i%lu\n", inode->i_ino);
++ au_iinfo_fin(inode);
++ cache_free_icntnr(container_of(inode, struct aufs_icntnr, vfs_inode));
++}
++
++//todo: how about merge with alloc_inode()?
++static void aufs_read_inode(struct inode *inode)
++{
++ int err;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++
++ err = au_iinfo_init(inode);
++ //if (LktrCond) err = -1;
++ if (!err) {
++ inode->i_version++;
++ inode->i_op = &aufs_iop;
++ inode->i_fop = &aufs_file_fop;
++ inode->i_mapping->a_ops = &aufs_aop;
++ return; /* success */
++ }
++
++ LKTRTrace("intializing inode info failed(%d)\n", err);
++ make_bad_inode(inode);
++}
++
++int au_show_brs(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ char a[16];
++ struct dentry *root;
++
++ TraceEnter();
++ SiMustAnyLock(sb);
++ root = sb->s_root;
++ DiMustAnyLock(root);
++
++ err = 0;
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ err = br_perm_str(a, sizeof(a), sbr_perm(sb, bindex));
++ if (!err)
++ err = seq_path(seq, sbr_mnt(sb, bindex),
++ au_h_dptr_i(root, bindex), au_esc_chars);
++ if (err > 0)
++ err = seq_printf(seq, "=%s", a);
++ if (!err && bindex != bend)
++ err = seq_putc(seq, ':');
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ int err, n;
++ struct super_block *sb;
++ struct aufs_sbinfo *sbinfo;
++ struct dentry *root;
++ struct file *xino;
++
++ TraceEnter();
++
++ sb = mnt->mnt_sb;
++ root = sb->s_root;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (au_flag_test(sb, AuFlag_XINO)) {
++ err = seq_puts(m, ",xino=");
++ if (unlikely(err))
++ goto out;
++ xino = stobr(sb, 0)->br_xino;
++ err = seq_path(m, xino->f_vfsmnt, xino->f_dentry, au_esc_chars);
++ if (unlikely(err <= 0))
++ goto out;
++ err = 0;
++
++#define Deleted "\\040(deleted)"
++ m->count -= sizeof(Deleted) - 1;
++ DEBUG_ON(memcmp(m->buf + m->count, Deleted,
++ sizeof(Deleted) - 1));
++#undef Deleted
++ } else
++ err = seq_puts(m, ",noxino");
++
++ n = au_flag_test(sb, AuFlag_PLINK);
++ if (unlikely(!err && (AuDefFlags & AuFlag_PLINK) != n))
++ err = seq_printf(m, ",%splink", n ? "" : "no");
++ n = au_flag_test_udba(sb);
++ if (unlikely(!err && (AuDefFlags & AuMask_UDBA) != n))
++ err = seq_printf(m, ",udba=%s", udba_str(n));
++ n = au_flag_test(sb, AuFlag_ALWAYS_DIROPQ);
++ if (unlikely(!err && (AuDefFlags & AuFlag_ALWAYS_DIROPQ) != n))
++ err = seq_printf(m, ",diropq=%c", n ? 'a' : 'w');
++ n = au_flag_test(sb, AuFlag_DLGT);
++ if (unlikely(!err && (AuDefFlags & AuFlag_DLGT) != n))
++ err = seq_printf(m, ",%sdlgt", n ? "" : "no");
++ n = au_flag_test(sb, AuFlag_WARN_PERM);
++ if (unlikely(!err && (AuDefFlags & AuFlag_WARN_PERM) != n))
++ err = seq_printf(m, ",%swarn_perm", n ? "" : "no");
++
++ sbinfo = stosi(sb);
++ n = sbinfo->si_dirwh;
++ if (unlikely(!err && n != AUFS_DIRWH_DEF))
++ err = seq_printf(m, ",dirwh=%d", n);
++ n = sbinfo->si_rdcache / HZ;
++ if (unlikely(!err && n != AUFS_RDCACHE_DEF))
++ err = seq_printf(m, ",rdcache=%d", n);
++#if 0
++ n = au_flag_test_coo(sb);
++ if (unlikely(!err && (AuDefFlags & AuMask_COO) != n))
++ err = seq_printf(m, ",coo=%s", coo_str(n));
++#endif
++
++ if (!err && !sysaufs_brs) {
++#ifdef CONFIG_AUFS_COMPAT
++ err = seq_puts(m, ",dirs=");
++#else
++ err = seq_puts(m, ",br:");
++#endif
++ if (!err)
++ err = au_show_brs(m, sb);
++ }
++
++ out:
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ TraceErr(err);
++ if (err)
++ err = -E2BIG;
++ TraceErr(err);
++ return err;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#define StatfsLock(d) aufs_read_lock((d)->d_sb->s_root, 0)
++#define StatfsUnlock(d) aufs_read_unlock((d)->d_sb->s_root, 0)
++#define StatfsArg(d) au_h_dptr((d)->d_sb->s_root)
++#define StatfsHInode(d) (StatfsArg(d)->d_inode)
++#define StatfsSb(d) ((d)->d_sb)
++static int aufs_statfs(struct dentry *arg, struct kstatfs *buf)
++#else
++#define StatfsLock(s) si_read_lock(s)
++#define StatfsUnlock(s) si_read_unlock(s)
++#define StatfsArg(s) sbr_sb(s, 0)
++#define StatfsHInode(s) (StatfsArg(s)->s_root->d_inode)
++#define StatfsSb(s) (s)
++static int aufs_statfs(struct super_block *arg, struct kstatfs *buf)
++#endif
++{
++ int err;
++
++ TraceEnter();
++
++ StatfsLock(arg);
++ err = vfsub_statfs(StatfsArg(arg), buf, need_dlgt(StatfsSb(arg)));
++ //if (LktrCond) err = -1;
++ StatfsUnlock(arg);
++ if (!err) {
++ //buf->f_type = AUFS_SUPER_MAGIC;
++ buf->f_type = 0;
++ buf->f_namelen -= AUFS_WH_PFX_LEN;
++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
++ }
++ //buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
++
++ TraceErr(err);
++ return err;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) || defined(UbuntuEdgy17Umount18)
++#define UmountBeginSb(mnt) (mnt)->mnt_sb
++static void aufs_umount_begin(struct vfsmount *arg, int flags)
++#else
++#define UmountBeginSb(sb) sb
++static void aufs_umount_begin(struct super_block *arg)
++#endif
++{
++ struct super_block *sb = UmountBeginSb(arg);
++
++ if (unlikely(!stosi(sb)))
++ return;
++
++ //au_wkq_wait_nwtask();
++ si_write_lock(sb);
++ if (au_flag_test(sb, AuFlag_PLINK)) {
++ au_put_plink(sb);
++ //kobj_umount(stosi(sb));
++ }
++#if 0
++ if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ shrink_dcache_sb(sb);
++#endif
++ si_write_unlock(sb);
++}
++
++static void free_sbinfo(struct aufs_sbinfo *sbinfo)
++{
++ TraceEnter();
++ DEBUG_ON(!sbinfo
++ || !list_empty(&sbinfo->si_plink));
++
++ free_branches(sbinfo);
++ kfree(sbinfo->si_branch);
++ kfree(sbinfo);
++}
++
++/* final actions when unmounting a file system */
++static void aufs_put_super(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++
++ sbinfo = stosi(sb);
++ if (unlikely(!sbinfo))
++ return;
++
++ sysaufs_del(sbinfo);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(UbuntuEdgy17Umount18)
++ // umount_begin() may not be called.
++ aufs_umount_begin(sb);
++#endif
++ free_sbinfo(sbinfo);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * refresh directories at remount time.
++ */
++static int do_refresh_dir(struct dentry *dentry, unsigned int flags)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ di_write_lock_child(dentry);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ err = au_refresh_hdentry(dentry, S_IFDIR);
++ if (err >= 0) {
++ err = au_refresh_hinode(inode, dentry);
++ if (!err)
++ au_reset_hinotify(inode, flags);
++ }
++ if (unlikely(err))
++ Err("unrecoverable error %d\n", err);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ dput(parent);
++ di_write_unlock(dentry);
++
++ TraceErr(err);
++ return err;
++}
++
++static int test_dir(struct dentry *dentry, void *arg)
++{
++ return S_ISDIR(dentry->d_inode->i_mode);
++}
++
++static int refresh_dir(struct dentry *root, int sgen)
++{
++ int err, i, j, ndentry;
++ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ LKTRTrace("sgen %d\n", sgen);
++ SiMustWriteLock(root->d_sb);
++ DEBUG_ON(au_digen(root) != sgen);
++ DiMustWriteLock(root);
++
++ err = au_dpages_init(&dpages, GFP_KERNEL);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, test_dir, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; !err && j < ndentry; j++) {
++ struct dentry *d;
++ d = dentries[j];
++ DEBUG_ON(!S_ISDIR(d->d_inode->i_mode)
++ || IS_ROOT(d)
++ || au_digen(d->d_parent) != sgen);
++ if (au_digen(d) != sgen)
++ err = do_refresh_dir(d, flags);
++ }
++ }
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++ TraceErr(err);
++
++ switch (err) {
++ case -ENOENT:
++ case -ENOTDIR:
++ case -EEXIST:
++ case -EIO:
++ err = -EINVAL;
++ }
++ return err;
++}
++
++/* protected by s_umount */
++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++ int err, do_refresh;
++ struct dentry *root;
++ struct inode *inode;
++ struct opts opts;
++ unsigned int given, dlgt;
++
++ //au_debug_on();
++ LKTRTrace("flags 0x%x, data %s, len %d\n",
++ *flags, data ? data : "NULL", data ? strlen(data) : 0);
++
++ err = 0;
++ if (unlikely(!data || !*data))
++ goto out; /* success */
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void*)__get_free_page(GFP_KERNEL);
++ //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++
++ /* parse it before aufs lock */
++ err = au_parse_opts(sb, data, &opts);
++ //if (LktrCond) {au_free_opts(&opts); err = -1;}
++ if (unlikely(err))
++ goto out_opts;
++
++ root = sb->s_root;
++ inode = root->d_inode;
++ i_lock(inode);
++ aufs_write_lock(root);
++
++ //DbgSleep(3);
++
++ /* au_do_opts() may return an error */
++ do_refresh = 0;
++ given = 0;
++ err = au_do_opts_remount(sb, &opts, &do_refresh, &given);
++ //if (LktrCond) err = -1;
++ au_free_opts(&opts);
++
++ if (do_refresh) {
++ int rerr;
++ struct aufs_sbinfo *sbinfo;
++
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_DLGT);
++ au_sigen_inc(sb);
++ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++ sbinfo = stosi(sb);
++ sbinfo->si_failed_refresh_dirs = 0;
++ rerr = refresh_dir(root, au_sigen(sb));
++ if (unlikely(rerr)) {
++ sbinfo->si_failed_refresh_dirs = 1;
++ Warn("Refreshing directories failed, ignores (%d)\n",
++ rerr);
++ }
++ au_cpup_attr_all(inode);
++ au_flag_set(sb, dlgt);
++ }
++
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ /* braces are added to stop a warning */
++ if (do_refresh) {
++ sysaufs_notify_remount();
++ }
++
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ err = cvt_err(err);
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++static struct super_operations aufs_sop = {
++ .alloc_inode = aufs_alloc_inode,
++ .destroy_inode = aufs_destroy_inode,
++ .read_inode = aufs_read_inode,
++ //.dirty_inode = aufs_dirty_inode,
++ //.write_inode = aufs_write_inode,
++ //void (*put_inode) (struct inode *);
++ .drop_inode = generic_delete_inode,
++ //.delete_inode = aufs_delete_inode,
++ //.clear_inode = aufs_clear_inode,
++
++ .show_options = aufs_show_options,
++ .statfs = aufs_statfs,
++
++ .put_super = aufs_put_super,
++ //void (*write_super) (struct super_block *);
++ //int (*sync_fs)(struct super_block *sb, int wait);
++ //void (*write_super_lockfs) (struct super_block *);
++ //void (*unlockfs) (struct super_block *);
++ .remount_fs = aufs_remount_fs,
++ // depends upon umount flags. also use put_super() (< 2.6.18)
++ .umount_begin = aufs_umount_begin
++};
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * at first mount time.
++ */
++
++static int alloc_sbinfo(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++
++ sbinfo = kmalloc(sizeof(*sbinfo), GFP_KERNEL);
++ //if (LktrCond) {kfree(sbinfo); sbinfo = NULL;}
++ if (unlikely(!sbinfo))
++ goto out;
++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_KERNEL);
++ //if (LktrCond) {kfree(sbinfo->si_branch); sbinfo->si_branch = NULL;}
++ if (unlikely(!sbinfo->si_branch)) {
++ kfree(sbinfo);
++ goto out;
++ }
++ rw_init_wlock(&sbinfo->si_rwsem);
++ sbinfo->si_bend = -1;
++ atomic_long_set(&sbinfo->si_xino, AUFS_FIRST_INO);
++ spin_lock_init(&sbinfo->si_plink_lock);
++ INIT_LIST_HEAD(&sbinfo->si_plink);
++ init_lvma(sbinfo);
++ sbinfo->si_generation = 0;
++ sbinfo->si_last_br_id = 0;
++ sbinfo->si_failed_refresh_dirs = 0;
++ sbinfo->si_flags = 0;
++ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
++ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++ //atomic_set(&sbinfo->si_hinotify, 0);
++ //init_waitqueue_head(&sbinfo->si_hinotify_wq);
++
++ sb->s_fs_info = sbinfo;
++ au_flag_set(sb, AuDefFlags);
++#ifdef ForceInotify
++ udba_set(sb, AuFlag_UDBA_INOTIFY);
++#endif
++#ifdef ForceDlgt
++ au_flag_set(sb, AuFlag_DLGT);
++#endif
++#ifdef ForceNoPlink
++ au_flag_clr(sb, AuFlag_PLINK);
++#endif
++ return 0; /* success */
++
++ out:
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
++
++static int alloc_root(struct super_block *sb)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *root;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ inode = iget(sb, AUFS_ROOT_INO);
++ //if (LktrCond) {iput(inode); inode = NULL;}
++ if (unlikely(!inode))
++ goto out;
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++ err = -ENOMEM;
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ root = d_alloc_root(inode);
++ //if (LktrCond) {igrab(inode); dput(root); root = NULL;}
++ if (unlikely(!root))
++ goto out_iput;
++ err = PTR_ERR(root);
++ if (IS_ERR(root))
++ goto out_iput;
++
++ err = au_alloc_dinfo(root);
++ //if (LktrCond){rw_write_unlock(&dtodi(root)->di_rwsem);err=-1;}
++ if (!err) {
++ sb->s_root = root;
++ return 0; /* success */
++ }
++ dput(root);
++ goto out; /* do not iput */
++
++ out_iput:
++ iput(inode);
++ out:
++ TraceErr(err);
++ return err;
++
++}
++
++static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
++{
++ int err;
++ struct dentry *root;
++ struct inode *inode;
++ struct opts opts;
++ char *arg = raw_data;
++
++ //au_debug_on();
++ if (unlikely(!arg || !*arg)) {
++ err = -EINVAL;
++ Err("no arg\n");
++ goto out;
++ }
++ LKTRTrace("%s, silent %d\n", arg, silent);
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void*)__get_free_page(GFP_KERNEL);
++ //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++
++ err = alloc_sbinfo(sb);
++ //if (LktrCond) {si_write_unlock(sb);free_sbinfo(stosi(sb));err=-1;}
++ if (unlikely(err))
++ goto out_opts;
++ SiMustWriteLock(sb);
++ /* all timestamps always follow the ones on the branch */
++ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
++ sb->s_op = &aufs_sop;
++ au_init_export_op(sb);
++ //err = kobj_mount(stosi(sb));
++ //if (err)
++ //goto out_info;
++
++ err = alloc_root(sb);
++ //if (LktrCond) {rw_write_unlock(&dtodi(sb->s_root)->di_rwsem);
++ //dput(sb->s_root);sb->s_root=NULL;err=-1;}
++ if (unlikely(err)) {
++ DEBUG_ON(sb->s_root);
++ si_write_unlock(sb);
++ goto out_info;
++ }
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ inode->i_nlink = 2;
++
++ /*
++ * actually we can parse options regardless aufs lock here.
++ * but at remount time, parsing must be done before aufs lock.
++ * so we follow the same rule.
++ */
++ ii_write_lock_parent(inode);
++ aufs_write_unlock(root);
++ err = au_parse_opts(sb, arg, &opts);
++ //if (LktrCond) {au_free_opts(&opts); err = -1;}
++ if (unlikely(err))
++ goto out_root;
++
++ /* lock vfs_inode first, then aufs. */
++ i_lock(inode);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ aufs_write_lock(root);
++
++ sb->s_maxbytes = 0;
++ err = au_do_opts_mount(sb, &opts);
++ //if (LktrCond) err = -1;
++ au_free_opts(&opts);
++ if (unlikely(err))
++ goto out_unlock;
++ DEBUG_ON(!sb->s_maxbytes);
++
++ //DbgDentry(root);
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ //DbgSb(sb);
++ goto out_opts; /* success */
++
++ out_unlock:
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ out_root:
++ dput(root);
++ sb->s_root = NULL;
++ out_info:
++ free_sbinfo(stosi(sb));
++ sb->s_fs_info = NULL;
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ TraceErr(err);
++ err = cvt_err(err);
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++static int aufs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *raw_data,
++ struct vfsmount *mnt)
++{
++ int err;
++
++ /* all timestamps always follow the ones on the branch */
++ //mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME;
++ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
++ if (!err) {
++ struct aufs_sbinfo *sbinfo = stosi(mnt->mnt_sb);
++ sbinfo->si_mnt = mnt;
++ sysaufs_add(sbinfo);
++ }
++ return err;
++}
++#else
++static struct super_block *aufs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name,
++ void *raw_data)
++{
++ return get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super);
++}
++#endif
++
++struct file_system_type aufs_fs_type = {
++ .name = AUFS_FSTYPE,
++ .fs_flags = FS_REVAL_DOT, // for UDBA and NFS branch
++ .get_sb = aufs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ //no need to __module_get() and module_put().
++ .owner = THIS_MODULE,
++};
+diff --git a/fs/aufs/super.h b/fs/aufs/super.h
+new file mode 100755
+index 0000000..56ddee1
+--- /dev/null
++++ b/fs/aufs/super.h
+@@ -0,0 +1,339 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: super.h,v 1.44 2007/05/14 03:39:54 sfjro Exp $ */
++
++#ifndef __AUFS_SUPER_H__
++#define __AUFS_SUPER_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "sysaufs.h"
++
++#ifdef CONFIG_AUFS_SYSAUFS
++/* entries under sysfs per mount-point */
++enum {SysaufsSb_XINO, /* SysaufsSb_PLINK, */ SysaufsSb_Last};
++struct sysaufs_sbinfo {
++ au_subsys_t subsys;
++ struct sysaufs_entry array[SysaufsSb_Last];
++};
++extern sysaufs_op au_si_ops[];
++#else
++struct sysaufs_sbinfo {};
++#endif
++
++struct aufs_sbinfo {
++ struct aufs_rwsem si_rwsem;
++
++ /* branch management */
++ /* wrap around attack by superuser? No. */
++ int si_generation;
++
++ /*
++ * set true when refresh_dirs() at remount time failed.
++ * then try refreshing dirs at access time again.
++ * if it is false, refreshing dirs at access time is unnecesary
++ */
++ unsigned int si_failed_refresh_dirs:1;
++
++ aufs_bindex_t si_bend;
++ aufs_bindex_t si_last_br_id;
++ struct aufs_branch **si_branch;
++
++ /* mount flags */
++ unsigned int si_flags;
++
++ /* external inode number table */
++ atomic_long_t si_xino; // time bomb
++ //struct file *si_xino_bmap;
++
++ /* readdir cache time, max, in HZ */
++ unsigned long si_rdcache;
++
++ /*
++ * If the number of whiteouts are larger than si_dirwh, leave all of
++ * them after rename_whtmp to reduce the cost of rmdir(2).
++ * future fsck.aufs or kernel thread will remove them later.
++ * Otherwise, remove all whiteouts and the dir in rmdir(2).
++ */
++ unsigned int si_dirwh;
++
++ /* pseudo_link list */ // dirty
++ spinlock_t si_plink_lock;
++ struct list_head si_plink;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++ /* super_blocks list is not exported */
++ struct list_head si_list;
++ struct vfsmount *si_mnt; /* no get/put */
++#endif
++
++ /* sysfs */
++ struct sysaufs_sbinfo si_sysaufs;
++
++#ifdef CONFIG_AUFS_HINOTIFY
++ /* hinotify */
++ //atomic_t si_hinotify;
++ //wait_queue_head_t si_hinotify_wq;
++#endif
++
++#ifdef CONFIG_AUFS_ROBR
++ /* locked vma list for mmap() */ // very dirty
++ spinlock_t si_lvma_lock;
++ struct list_head si_lvma;
++#endif
++};
++
++/* an entry in a xino file */
++struct xino {
++ ino_t ino;
++ //__u32 h_gen;
++} __attribute__ ((packed));
++
++//#define AuXino_INVALID_HGEN (-1)
++
++/* ---------------------------------------------------------------------- */
++
++/* Mount flags */
++#define AuFlag_XINO 1
++#define AuFlag_ZXINO (1 << 1)
++#define AuFlag_PLINK (1 << 2)
++#define AuFlag_UDBA_NONE (1 << 3)
++#define AuFlag_UDBA_REVAL (1 << 4)
++#define AuFlag_UDBA_INOTIFY (1 << 5)
++#define AuFlag_WARN_PERM (1 << 6)
++#define AuFlag_COO_NONE (1 << 7)
++#define AuFlag_COO_LEAF (1 << 8)
++#define AuFlag_COO_ALL (1 << 9)
++#define AuFlag_ALWAYS_DIROPQ (1 << 10)
++#define AuFlag_DLGT (1 << 11)
++
++#define AuMask_UDBA (AuFlag_UDBA_NONE | AuFlag_UDBA_REVAL \
++ | AuFlag_UDBA_INOTIFY)
++#define AuMask_COO (AuFlag_COO_NONE | AuFlag_COO_LEAF \
++ | AuFlag_COO_ALL)
++
++#ifdef CONFIG_AUFS_COMPAT
++#define AuDefFlag_DIROPQ AuFlag_ALWAYS_DIROPQ
++#else
++#define AuDefFlag_DIROPQ 0
++#endif
++
++#define AuDefFlags_COMM (AuFlag_XINO | AuFlag_UDBA_REVAL | AuFlag_WARN_PERM \
++ | AuFlag_COO_NONE | AuDefFlag_DIROPQ)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#define AuDefFlags (AuDefFlags_COMM | AuFlag_PLINK)
++#else
++#define AuDefFlags AuDefFlags_COMM
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* flags for aufs_read_lock()/di_read_lock() */
++#define AUFS_D_WLOCK 1
++#define AUFS_I_RLOCK 2
++#define AUFS_I_WLOCK 4
++
++/* ---------------------------------------------------------------------- */
++
++/* super.c */
++int au_show_brs(struct seq_file *seq, struct super_block *sb);
++
++/* xino.c */
++struct file *xino_create(struct super_block *sb, char *fname, int silent,
++ struct dentry *parent);
++ino_t xino_new_ino(struct super_block *sb);
++int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino);
++int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino);
++int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino);
++int xino_init(struct super_block *sb, aufs_bindex_t bindex,
++ struct file *base_file, int do_test);
++struct opt_xino;
++int xino_set(struct super_block *sb, struct opt_xino *xino, int remount);
++int xino_clr(struct super_block *sb);
++struct file *xino_def(struct super_block *sb);
++
++/* sbinfo.c */
++struct aufs_sbinfo *stosi(struct super_block *sb);
++aufs_bindex_t sbend(struct super_block *sb);
++struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex);
++int au_sigen(struct super_block *sb);
++int au_sigen_inc(struct super_block *sb);
++int find_bindex(struct super_block *sb, struct aufs_branch *br);
++
++void aufs_read_lock(struct dentry *dentry, int flags);
++void aufs_read_unlock(struct dentry *dentry, int flags);
++void aufs_write_lock(struct dentry *dentry);
++void aufs_write_unlock(struct dentry *dentry);
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++aufs_bindex_t new_br_id(struct super_block *sb);
++
++/* ---------------------------------------------------------------------- */
++
++static inline const char *au_sbtype(struct super_block *sb)
++{
++ return sb->s_type->name;
++}
++
++static inline int au_is_aufs(struct super_block *sb)
++{
++ return !strcmp(au_sbtype(sb), AUFS_FSTYPE);
++}
++
++static inline int au_is_nfs(struct super_block *sb)
++{
++#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "nfs");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_is_remote(struct super_block *sb)
++{
++ return au_is_nfs(sb);
++}
++
++#ifdef CONFIG_AUFS_EXPORT
++static inline void au_init_export_op(struct super_block *sb)
++{
++ extern struct export_operations aufs_export_op;
++ sb->s_export_op = &aufs_export_op;
++}
++
++static inline int au_is_nfsd(struct task_struct *tsk)
++{
++ return (!tsk->mm && !strcmp(tsk->comm, "nfsd"));
++}
++
++static inline void au_nfsd_lockdep_off(void)
++{
++ /* braces are added to stop a warning */
++ if (au_is_nfsd(current)) {
++ lockdep_off();
++ }
++}
++
++static inline void au_nfsd_lockdep_on(void)
++{
++ /* braces are added to stop a warning */
++ if (au_is_nfsd(current)) {
++ lockdep_on();
++ }
++}
++#else
++static inline int au_is_nfsd(struct task_struct *tsk)
++{
++ return 0;
++}
++static inline void au_init_export_op(struct super_block *sb)
++{
++ /* nothing */
++}
++#define au_nfsd_lockdep_off() /* */
++#define au_nfsd_lockdep_on() /* */
++#endif /* CONFIG_AUFS_EXPORT */
++
++static inline void init_lvma(struct aufs_sbinfo *sbinfo)
++{
++#ifdef CONFIG_AUFS_ROBR
++ spin_lock_init(&sbinfo->si_lvma_lock);
++ INIT_LIST_HEAD(&sbinfo->si_lvma);
++#else
++ /* nothing */
++#endif
++}
++
++/* limited support before 2.6.18 */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++static inline void au_mntget(struct super_block *sb)
++{
++ mntget(stosi(sb)->si_mnt);
++}
++
++static inline void au_mntput(struct super_block *sb)
++{
++ mntput(stosi(sb)->si_mnt);
++}
++#else
++static inline void au_mntget(struct super_block *sb)
++{
++ /* empty */
++}
++
++static inline void au_mntput(struct super_block *sb)
++{
++ /* empty */
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static inline void au_flag_set(struct super_block *sb, unsigned int flag)
++{
++ //SiMustWriteLock(sb);
++ stosi(sb)->si_flags |= flag;
++}
++
++static inline void au_flag_clr(struct super_block *sb, unsigned int flag)
++{
++ //SiMustWriteLock(sb);
++ stosi(sb)->si_flags &= ~flag;
++}
++
++static inline
++unsigned int au_flag_test(struct super_block *sb, unsigned int flag)
++{
++ //SiMustAnyLock(sb);
++ return stosi(sb)->si_flags & flag;
++}
++
++static inline unsigned int au_flag_test_udba(struct super_block *sb)
++{
++ return au_flag_test(sb, AuMask_UDBA);
++}
++
++static inline unsigned int au_flag_test_coo(struct super_block *sb)
++{
++ return au_flag_test(sb, AuMask_COO);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock superblock. mainly for entry point functions */
++/*
++ * si_read_lock, si_write_lock,
++ * si_read_unlock, si_write_unlock, si_downgrade_lock
++ */
++SimpleRwsemFuncs(si, struct super_block *sb, stosi(sb)->si_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define SiMustReadLock(sb) RwMustReadLock(&stosi(sb)->si_rwsem)
++#define SiMustWriteLock(sb) RwMustWriteLock(&stosi(sb)->si_rwsem)
++#define SiMustAnyLock(sb) RwMustAnyLock(&stosi(sb)->si_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SUPER_H__ */
+diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
+new file mode 100755
+index 0000000..d686862
+--- /dev/null
++++ b/fs/aufs/sysaufs.c
+@@ -0,0 +1,620 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sysaufs.c,v 1.6 2007/05/14 03:40:10 sfjro Exp $ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* super_blocks list is not exported */
++static DEFINE_MUTEX(aufs_sbilist_mtx);
++static LIST_HEAD(aufs_sbilist);
++
++/* ---------------------------------------------------------------------- */
++
++typedef ssize_t (*rwfunc_t)(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args);
++static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args);
++static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf, loff_t
++ offset, size_t sz, struct sysaufs_args *args);
++
++#define GFunc(name, _index, func) \
++static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
++{ \
++ struct sysaufs_args args = { \
++ .index = (_index), \
++ .mtx = &aufs_sbilist_mtx, \
++ .sb = NULL \
++ }; \
++ return func(kobj, buf, offset, sz, &args); \
++}
++
++#define GFuncs(name, _index) \
++ GFunc(read_##name, _index, sysaufs_read); \
++ GFunc(write_##name, _index, sysaufs_free_write);
++
++static struct super_block *find_sb_locked(struct kobject *kobj)
++{
++ struct super_block *sb;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ sb = NULL;
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ if (&au_subsys_to_kset(sbinfo->si_sysaufs.subsys).kobj != kobj)
++ continue;
++ sb = sbinfo->si_mnt->mnt_sb;
++ si_read_lock(sb);
++ break;
++ }
++ return sb;
++}
++
++static ssize_t sb_func(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args, rwfunc_t func)
++{
++ ssize_t err;
++
++ err = -ENOENT;
++ mutex_lock(&aufs_sbilist_mtx);
++ args->sb = find_sb_locked(kobj);
++ if (args->sb) {
++ err = func(kobj, buf, offset, sz, args);
++ si_read_unlock(args->sb);
++ }
++ mutex_unlock(&aufs_sbilist_mtx);
++ return err;
++}
++
++#define SbFunc(name, _index, func) \
++static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
++{ \
++ struct sysaufs_args args = { \
++ .index = (_index), \
++ .mtx = NULL \
++ }; \
++ return sb_func(kobj, buf, offset, sz, &args, func); \
++}
++
++#define SbFuncs(name, index) \
++ SbFunc(read_##name, index, sysaufs_read); \
++ SbFunc(write_##name, index, sysaufs_free_write)
++
++static decl_subsys(aufs, NULL, NULL);
++enum {Brs, Stat, Config, _Last};
++static struct sysaufs_entry g_array[_Last];
++GFuncs(brs, Brs);
++GFuncs(stat, Stat);
++GFuncs(config, Config);
++
++SbFuncs(xino, SysaufsSb_XINO);
++
++#define SetEntry(e, _name, init_size, _ops) \
++ do { \
++ (e)->attr.attr.name = #_name; \
++ (e)->attr.attr.owner = THIS_MODULE; \
++ (e)->attr.attr.mode = S_IRUGO | S_IWUSR; \
++ (e)->attr.read = read_##_name; \
++ (e)->attr.write = write_##_name; \
++ (e)->allocated = init_size; \
++ (e)->err = -1; \
++ (e)->ops = _ops; \
++ } while (0)
++
++#define Priv(e) (e)->attr.private
++#define Allocated(e) (e)->allocated
++#define Len(e) (e)->attr.size
++#define Name(e) attr_name((e)->attr)
++
++/* ---------------------------------------------------------------------- */
++
++static void free_entry(struct sysaufs_entry *e)
++{
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(!Priv(e));
++
++ if (Allocated(e) > 0)
++ kfree(Priv(e));
++ else
++ free_pages((unsigned long)Priv(e), -Allocated(e));
++ Priv(e) = NULL;
++ Len(e) = 0;
++}
++
++static void free_entries(void)
++{
++ static int a[] = {Brs, -1};
++ int *p = a;
++
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ while (*p >= 0) {
++ if (Priv(g_array + *p))
++ free_entry(g_array + *p);
++ p++;
++ }
++}
++
++static int alloc_entry(struct sysaufs_entry *e)
++{
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(Priv(e));
++ //Dbg("%d\n", Allocated(e));
++
++ if (Allocated(e) > 0)
++ Priv(e) = kmalloc(Allocated(e), GFP_KERNEL);
++ else
++ Priv(e) = (void*)__get_free_pages(GFP_KERNEL, -Allocated(e));
++ if (Priv(e))
++ return 0;
++ return -ENOMEM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void unreg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
++ au_subsys_t *parent)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < n; i++, a++)
++ if (!a->err) {
++ sysfs_remove_bin_file
++ (&au_subsys_to_kset(*subsys).kobj, &a->attr);
++ if (Priv(a))
++ free_entry(a);
++ }
++
++ subsystem_unregister(subsys);
++ subsys_put(parent);
++}
++
++static int reg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
++ au_subsys_t *parent)
++{
++ int err, i;
++
++ TraceEnter();
++
++ subsys_get(parent);
++ kobj_set_kset_s(&au_subsys_to_kset(*subsys), *parent);
++ err = subsystem_register(subsys);
++ if (unlikely(err))
++ goto out;
++
++ for (i = 0; !err && i < n; i++)
++ err = a[i].err = sysfs_create_bin_file
++ (&au_subsys_to_kset(*subsys).kobj, &a[i].attr);
++ if (unlikely(err))
++ unreg(subsys, a, n, parent);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define SbSetEntry(index, name, init_size) \
++ SetEntry(sa->array + index, name, init_size, au_si_ops);
++
++void sysaufs_add(struct aufs_sbinfo *sbinfo)
++{
++ int err;
++ struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
++
++ TraceEnter();
++
++ mutex_lock(&aufs_sbilist_mtx);
++ list_add_tail(&sbinfo->si_list, &aufs_sbilist);
++ free_entries();
++
++ memset(sa, 0, sizeof(*sa));
++ SbSetEntry(SysaufsSb_XINO, xino, 128);
++ err = kobject_set_name(&au_subsys_to_kset(sa->subsys).kobj, "%p",
++ sbinfo->si_mnt->mnt_sb);
++ if (!err)
++ err = reg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array),
++ &aufs_subsys);
++ if (unlikely(err))
++ Warn("failed adding sysfs (%d)\n", err);
++
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++void sysaufs_del(struct aufs_sbinfo *sbinfo)
++{
++ struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
++
++ TraceEnter();
++
++ mutex_lock(&aufs_sbilist_mtx);
++ unreg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array), &aufs_subsys);
++ list_del(&sbinfo->si_list);
++ free_entries();
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++void sysaufs_notify_remount(void)
++{
++ mutex_lock(&aufs_sbilist_mtx);
++ free_entries();
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int make_brs(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(args->index != Brs);
++
++ err = 0;
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ struct super_block *sb;
++ struct dentry *root;
++ struct vfsmount *mnt;
++
++ sb = sbinfo->si_mnt->mnt_sb;
++ root = sb->s_root;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ mnt = sbinfo->si_mnt;
++ err = seq_escape
++ (seq, mnt->mnt_devname ? mnt->mnt_devname : "none",
++ au_esc_chars);
++ if (!err)
++ err = seq_putc(seq, ' ');
++ if (!err)
++ err = seq_path(seq, mnt, root, au_esc_chars);
++ if (err > 0)
++ err = seq_printf(seq, " %p br:", sb);
++ if (!err)
++ err = au_show_brs(seq, sb);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ if (!err)
++ err = seq_putc(seq, '\n');
++ else
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int make_config(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++
++ TraceEnter();
++ DEBUG_ON(args->index != Config);
++
++#ifdef CONFIG_AUFS
++ err = seq_puts(seq, "CONFIG_AUFS=y\n");
++#else
++ err = seq_puts(seq, "CONFIG_AUFS=m\n");
++#endif
++
++#define puts(m, v) \
++ if (!err) err = seq_puts(seq, "CONFIG_AUFS_" #m "=" #v "\n")
++#define puts_bool(m) puts(m, y)
++#define puts_mod(m) puts(m, m)
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ puts_bool(FAKE_DM);
++#endif
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++ puts_bool(BRANCH_MAX_127);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
++ puts_bool(BRANCH_MAX_511);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++ puts_bool(BRANCH_MAX_1023);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++ puts_bool(BRANCH_MAX_32767);
++#endif
++ puts_bool(SYSAUFS);
++#ifdef CONFIG_AUFS_HINOTIFY
++ puts_bool(HINOTIFY);
++#endif
++#ifdef CONFIG_AUFS_EXPORT
++ puts_bool(EXPORT);
++#endif
++#ifdef CONFIG_AUFS_ROBR
++ puts_bool(ROBR);
++#endif
++#ifdef CONFIG_AUFS_DLGT
++ puts_bool(DLGT);
++#endif
++#ifdef CONFIG_AUFS_LHASH_PATCH
++ puts_bool(LHASH_PATCH);
++#endif
++#ifdef CONFIG_AUFS_KSIZE_PATCH
++ puts_bool(KSIZE_PATCH);
++#endif
++#ifdef CONFIG_AUFS_DEBUG
++ puts_bool(DEBUG);
++#endif
++#ifdef CONFIG_AUFS_COMPAT
++ puts_bool(COMPAT);
++#endif
++
++#undef puts_bool
++#undef puts
++
++ TraceErr(err);
++ return err;
++}
++
++static int make_stat(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err, i;
++
++ TraceEnter();
++ DEBUG_ON(args->index != Stat);
++
++ *do_size = 0;
++ err = seq_puts(seq, "wkq max_busy:");
++ for (i = 0; !err && i < aufs_nwkq; i++)
++ err = seq_printf(seq, " %u", au_wkq[i].max_busy);
++ if (!err)
++ err = seq_printf(seq, ", %u(generic)\n",
++ au_wkq[aufs_nwkq].max_busy);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int make(struct sysaufs_entry *e, struct sysaufs_args *args,
++ int *do_size)
++
++{
++ int err;
++ struct seq_file *seq;
++
++ TraceEnter();
++ DEBUG_ON(Priv(e));
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ err = -ENOMEM;
++ seq = kzalloc(sizeof(*seq), GFP_KERNEL);
++ if (unlikely(!seq))
++ goto out;
++
++ Len(e) = 0;
++ while (1) {
++ err = alloc_entry(e);
++ if (unlikely(err))
++ break;
++
++ //mutex_init(&seq.lock);
++ seq->buf = Priv(e);
++ seq->count = 0;
++ seq->size = Allocated(e);
++ if (unlikely(Allocated(e) <= 0))
++ seq->size = PAGE_SIZE << -Allocated(e);
++
++ err = e->ops[args->index](seq, args, do_size);
++ if (!err) {
++ Len(e) = seq->count;
++ break; /* success */
++ }
++
++ free_entry(e);
++ if (Allocated(e) > 0) {
++ Allocated(e) <<= 1;
++ if (unlikely(Allocated(e) >= (int)PAGE_SIZE))
++ Allocated(e) = 0;
++ } else
++ Allocated(e)--;
++ //Dbg("%d\n", Allocated(e));
++ }
++ kfree(seq);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* why does sysfs pass my parent kobject? */
++static struct dentry *find_me(struct dentry *parent, struct sysaufs_entry *e)
++{
++#if 1
++ struct dentry *dentry;
++ const char *name = Name(e);
++ const unsigned int len = strlen(name);
++
++ //Dbg("%.*s\n", DLNPair(parent));
++ spin_lock(&dcache_lock);
++ list_for_each_entry(dentry, &parent->d_subdirs, D_CHILD) {
++ //Dbg("%.*s\n", DLNPair(dentry));
++ if (len == dentry->d_name.len
++ && !strcmp(dentry->d_name.name, name)) {
++ spin_unlock(&dcache_lock);
++ return dentry;
++ }
++ }
++ spin_unlock(&dcache_lock);
++#endif
++ return NULL;
++}
++
++static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args)
++{
++ ssize_t err;
++ loff_t len;
++ struct dentry *d;
++ struct sysaufs_entry *e;
++ int do_size;
++
++ LKTRTrace("{%d, %p}, offset %Ld, sz %lu\n",
++ args->index, args->sb, offset, (unsigned long)sz);
++
++ if (unlikely(!sz))
++ return 0;
++
++ err = 0;
++ d = NULL;
++ e = g_array + args->index;
++ if (args->sb)
++ e = stosi(args->sb)->si_sysaufs.array + args->index;
++
++ do_size = 1;
++ if (args->mtx)
++ mutex_lock(args->mtx);
++ if (unlikely(!Priv(e))) {
++ err = make(e, args, &do_size);
++ DEBUG_ON(Len(e) > INT_MAX);
++ if (do_size) {
++ d = find_me(kobj->dentry, e);
++ if (d)
++ i_size_write(d->d_inode, Len(e));
++ }
++ }
++
++ if (!err) {
++ err = len = Len(e) - offset;
++ LKTRTrace("%Ld\n", len);
++ if (len > 0) {
++ if (len > sz)
++ err = sz;
++ memcpy(buf, Priv(e) + offset, err);
++ }
++
++ if (!do_size)
++ free_entry(e);
++ }
++ if (args->mtx)
++ mutex_unlock(args->mtx);
++
++ TraceErr(err);
++ return err;
++}
++
++static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf,
++ loff_t offset, size_t sz,
++ struct sysaufs_args *args)
++{
++ struct dentry *d;
++ int allocated, len;
++ struct sysaufs_entry *e;
++
++ LKTRTrace("{%d, %p}\n", args->index, args->sb);
++
++ e = g_array + args->index;
++ if (args->sb)
++ e = stosi(args->sb)->si_sysaufs.array + args->index;
++
++ if (args->mtx)
++ mutex_lock(args->mtx);
++ if (Priv(e)) {
++ allocated = Allocated(e);
++ if (unlikely(allocated <= 0))
++ allocated = PAGE_SIZE << -allocated;
++ allocated >>= 1;
++ len = Len(e);
++
++ free_entry(e);
++ if (unlikely(len <= allocated)) {
++ if (Allocated(e) >= 0)
++ Allocated(e) = allocated;
++ else
++ Allocated(e)++;
++ }
++
++ d = find_me(kobj->dentry, e);
++ if (d && i_size_read(d->d_inode))
++ i_size_write(d->d_inode, 0);
++ }
++ if (args->mtx)
++ mutex_unlock(args->mtx);
++
++ return sz;
++}
++
++static sysaufs_op g_ops[] = {
++ [Brs] = make_brs,
++ [Stat] = make_stat,
++ [Config] = make_config
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define GSetEntry(index, name, init_size) \
++ SetEntry(g_array + index, name, init_size, g_ops)
++
++int __init sysaufs_init(void)
++{
++ int err;
++
++ GSetEntry(Brs, brs, 128);
++ GSetEntry(Stat, stat, 32);
++ GSetEntry(Config, config, 256);
++ err = reg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
++ TraceErr(err);
++ return err;
++}
++
++void __exit sysaufs_fin(void)
++{
++ mutex_lock(&aufs_sbilist_mtx);
++ unreg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef DbgDlgt
++int is_branch(struct super_block *h_sb)
++{
++ int found = 0;
++ struct aufs_sbinfo *sbinfo;
++
++ //Dbg("here\n");
++ mutex_lock(&aufs_sbilist_mtx);
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++
++ sb = sbinfo->si_mnt->mnt_sb;
++ si_read_lock(sb);
++ bend = sbend(sb);
++ for (bindex = 0; !found && bindex <= bend; bindex++)
++ found = (h_sb == sbr_sb(sb, bindex));
++ si_read_unlock(sb);
++ }
++ mutex_unlock(&aufs_sbilist_mtx);
++ return found;
++}
++#endif
+diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
+new file mode 100755
+index 0000000..cf0247f
+--- /dev/null
++++ b/fs/aufs/sysaufs.h
+@@ -0,0 +1,83 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sysaufs.h,v 1.3 2007/05/14 06:27:18 sfjro Exp $ */
++
++#ifndef __SYSAUFS_H__
++#define __SYSAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++typedef struct kset au_subsys_t;
++#define au_subsys_to_kset(subsys) (subsys)
++#else
++typedef struct subsystem au_subsys_t;
++#define au_subsys_to_kset(subsys) ((subsys).kset)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* arguments for an entry under sysfs */
++struct sysaufs_args {
++ int index;
++ struct mutex *mtx;
++ struct super_block *sb;
++};
++
++typedef int (*sysaufs_op)(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size);
++
++/* an entry under sysfs */
++struct sysaufs_entry {
++ struct bin_attribute attr;
++ int allocated; /* zero minus means pages */
++ int err;
++ sysaufs_op *ops;
++};
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_sbinfo;
++#ifdef CONFIG_AUFS_SYSAUFS
++void sysaufs_add(struct aufs_sbinfo *sbinfo);
++void sysaufs_del(struct aufs_sbinfo *sbinfo);
++int __init sysaufs_init(void);
++void sysaufs_fin(void);
++void sysaufs_notify_remount(void);
++#else
++static inline void sysaufs_add(struct aufs_sbinfo *sbinfo)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_del(struct aufs_sbinfo *sbinfo)
++{
++ /* nothing */
++}
++#define sysaufs_init() 0
++#define sysaufs_fin() /* */
++#define sysaufs_notify_remount() /* */
++#endif /* CONFIG_AUFS_SYSAUFS */
++
++#endif /* __KERNEL__ */
++#endif /* __SYSAUFS_H__ */
+diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c
+new file mode 100755
+index 0000000..8e99b7d
+--- /dev/null
++++ b/fs/aufs/vdir.c
+@@ -0,0 +1,802 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vdir.c,v 1.22 2007/05/14 03:38:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static int calc_size(int namelen)
++{
++ int sz;
++
++ sz = sizeof(struct aufs_de) + namelen;
++ if (sizeof(ino_t) == sizeof(long)) {
++ const int mask = sizeof(ino_t) - 1;
++ if (sz & mask) {
++ sz += sizeof(ino_t);
++ sz &= ~mask;
++ }
++ } else {
++#if 0 // remove
++ BUG();
++ // this block will be discarded by optimizer.
++ int m;
++ m = sz % sizeof(ino_t);
++ if (m)
++ sz += sizeof(ino_t) - m;
++#endif
++ }
++
++ DEBUG_ON(sz % sizeof(ino_t));
++ return sz;
++}
++
++static int set_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->p - p->p) {
++ p->de->de_str.len = 0;
++ //smp_mb();
++ return 0;
++ }
++ return -1; // error
++}
++
++/* returns true or false */
++static int is_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->p - p->p)
++ return !p->de->de_str.len;
++ return 1;
++}
++
++static aufs_deblk_t *last_deblk(struct aufs_vdir *vdir)
++{
++ return vdir->vd_deblk[vdir->vd_nblk - 1];
++}
++
++void nhash_init(struct aufs_nhash *nhash)
++{
++ int i;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++)
++ INIT_HLIST_HEAD(nhash->heads + i);
++}
++
++struct aufs_nhash *nhash_new(gfp_t gfp)
++{
++ struct aufs_nhash *nhash;
++
++ nhash = kmalloc(sizeof(*nhash), gfp);
++ if (nhash) {
++ nhash_init(nhash);
++ return nhash;
++ }
++ return ERR_PTR(-ENOMEM);
++}
++
++void nhash_del(struct aufs_nhash *nhash)
++{
++ nhash_fin(nhash);
++ kfree(nhash);
++}
++
++void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src)
++{
++ int i;
++
++ TraceEnter();
++
++ //DbgWhlist(src);
++ *dst = *src;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ struct hlist_head *h;
++ h = dst->heads + i;
++ if (h->first)
++ h->first->pprev = &h->first;
++ INIT_HLIST_HEAD(src->heads + i);
++ }
++ //DbgWhlist(src);
++ //DbgWhlist(dst);
++ //smp_mb();
++}
++
++/* ---------------------------------------------------------------------- */
++
++void nhash_fin(struct aufs_nhash *whlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos, *n;
++
++ TraceEnter();
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
++ //hlist_del(pos);
++ kfree(tpos);
++ }
++ }
++}
++
++int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit)
++{
++ int n, i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++
++ LKTRTrace("limit %d\n", limit);
++ //return 1;
++
++ n = 0;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ if (tpos->wh_bindex == btgt && ++n > limit)
++ return 1;
++ }
++ return 0;
++}
++
++/* returns found(true) or not */
++int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen)
++{
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ head = whlist->heads + au_name_hash(name, namelen);
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ str = &tpos->wh_str;
++ LKTRTrace("%.*s\n", str->len, str->name);
++ if (str->len == namelen && !memcmp(str->name, name, namelen))
++ return 1;
++ }
++ return 0;
++}
++
++int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct aufs_destr *str;
++ struct aufs_wh *wh;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ err = -ENOMEM;
++ wh = kmalloc(sizeof(*wh) + namelen, GFP_KERNEL);
++ if (unlikely(!wh))
++ goto out;
++ err = 0;
++ wh->wh_bindex = bindex;
++ str = &wh->wh_str;
++ str->len = namelen;
++ memcpy(str->name, name, namelen);
++ hlist_add_head(&wh->wh_hash,
++ whlist->heads + au_name_hash(name, namelen));
++ //smp_mb();
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void free_vdir(struct aufs_vdir *vdir)
++{
++ aufs_deblk_t **deblk;
++
++ TraceEnter();
++
++ deblk = vdir->vd_deblk;
++ while (vdir->vd_nblk--) {
++ kfree(*deblk);
++ deblk++;
++ }
++ kfree(vdir->vd_deblk);
++ cache_free_vdir(vdir);
++}
++
++static int append_deblk(struct aufs_vdir *vdir)
++{
++ int err, sz, i;
++ aufs_deblk_t **o;
++ union aufs_deblk_p p, deblk_end;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ sz = sizeof(*o) * vdir->vd_nblk;
++ o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_KERNEL);
++ if (unlikely(!o))
++ goto out;
++ vdir->vd_deblk = o;
++ p.deblk = kmalloc(sizeof(*p.deblk), GFP_KERNEL);
++ if (p.deblk) {
++ i = vdir->vd_nblk++;
++ vdir->vd_deblk[i] = p.deblk;
++ vdir->vd_last.i = i;
++ vdir->vd_last.p.p = p.p;
++ deblk_end.deblk = p.deblk + 1;
++ err = set_deblk_end(&p, &deblk_end);
++ DEBUG_ON(err);
++ }
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static struct aufs_vdir *alloc_vdir(void)
++{
++ struct aufs_vdir *vdir;
++ int err;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ vdir = cache_alloc_vdir();
++ if (unlikely(!vdir))
++ goto out;
++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_KERNEL);
++ if (unlikely(!vdir->vd_deblk))
++ goto out_free;
++
++ vdir->vd_nblk = 0;
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ err = append_deblk(vdir);
++ if (!err)
++ return vdir; /* success */
++
++ kfree(vdir->vd_deblk);
++
++ out_free:
++ cache_free_vdir(vdir);
++ out:
++ vdir = ERR_PTR(err);
++ TraceErrPtr(vdir);
++ return vdir;
++}
++
++static int reinit_vdir(struct aufs_vdir *vdir)
++{
++ int err;
++ union aufs_deblk_p p, deblk_end;
++
++ TraceEnter();
++
++ while (vdir->vd_nblk > 1) {
++ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
++ vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
++ vdir->vd_nblk--;
++ }
++ p.deblk = vdir->vd_deblk[0];
++ deblk_end.deblk = p.deblk + 1;
++ err = set_deblk_end(&p, &deblk_end);
++ DEBUG_ON(err);
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ vdir->vd_last.i = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ //smp_mb();
++ //DbgVdir(vdir);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void free_dehlist(struct aufs_nhash *dehlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_dehstr *tpos;
++ struct hlist_node *pos, *n;
++
++ TraceEnter();
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = dehlist->heads + i;
++ hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
++ //hlist_del(pos);
++ cache_free_dehstr(tpos);
++ }
++ }
++}
++
++/* returns found(true) or not */
++static int test_known(struct aufs_nhash *delist, char *name, int namelen)
++{
++ struct hlist_head *head;
++ struct aufs_dehstr *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ head = delist->heads + au_name_hash(name, namelen);
++ hlist_for_each_entry(tpos, pos, head, hash) {
++ str = tpos->str;
++ LKTRTrace("%.*s\n", str->len, str->name);
++ if (str->len == namelen && !memcmp(str->name, name, namelen))
++ return 1;
++ }
++ return 0;
++
++}
++
++static int append_de(struct aufs_vdir *vdir, char *name, int namelen, ino_t ino,
++ unsigned int d_type, struct aufs_nhash *delist)
++{
++ int err, sz;
++ union aufs_deblk_p p, *room, deblk_end;
++ struct aufs_dehstr *dehstr;
++
++ LKTRTrace("%.*s %d, i%lu, dt%u\n", namelen, name, namelen, ino, d_type);
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + 1;
++ room = &vdir->vd_last.p;
++ DEBUG_ON(room->p < p.p || deblk_end.p <= room->p
++ || !is_deblk_end(room, &deblk_end));
++
++ sz = calc_size(namelen);
++ if (unlikely(sz > deblk_end.p - room->p)) {
++ err = append_deblk(vdir);
++ if (unlikely(err))
++ goto out;
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + 1;
++ //smp_mb();
++ DEBUG_ON(room->p != p.p);
++ }
++
++ err = -ENOMEM;
++ dehstr = cache_alloc_dehstr();
++ if (unlikely(!dehstr))
++ goto out;
++ dehstr->str = &room->de->de_str;
++ hlist_add_head(&dehstr->hash,
++ delist->heads + au_name_hash(name, namelen));
++
++ room->de->de_ino = ino;
++ room->de->de_type = d_type;
++ room->de->de_str.len = namelen;
++ memcpy(room->de->de_str.name, name, namelen);
++
++ err = 0;
++ room->p += sz;
++ if (unlikely(set_deblk_end(room, &deblk_end)))
++ err = append_deblk(vdir);
++ //smp_mb();
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct fillvdir_arg {
++ struct file *file;
++ struct aufs_vdir *vdir;
++ struct aufs_nhash *delist;
++ struct aufs_nhash *whlist;
++ aufs_bindex_t bindex;
++ int err;
++ int called;
++};
++
++static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
++ filldir_ino_t h_ino, unsigned int d_type)
++{
++ struct fillvdir_arg *arg = __arg;
++ char *name = (void*)__name;
++ aufs_bindex_t bindex, bend;
++ struct xino xino;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, namelen %d, i%Lu, dt%u\n",
++ namelen, name, namelen, (u64)h_ino, d_type);
++
++ sb = arg->file->f_dentry->d_sb;
++ bend = arg->bindex;
++ arg->err = 0;
++ arg->called++;
++ //smp_mb();
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ for (bindex = 0; bindex < bend; bindex++)
++ if (test_known(arg->delist + bindex, name, namelen)
++ || test_known_wh(arg->whlist + bindex, name,
++ namelen))
++ goto out; /* already exists or whiteouted */
++
++ arg->err = xino_read(sb, bend, h_ino, &xino);
++ if (!arg->err && !xino.ino) {
++ //struct inode *h_inode;
++ xino.ino = xino_new_ino(sb);
++ if (unlikely(!xino.ino))
++ arg->err = -EIO;
++#if 0
++ //xino.h_gen = AuXino_INVALID_HGEN;
++ h_inode = ilookup(sbr_sb(sb, bend), h_ino);
++ if (h_inode) {
++ if (!is_bad_inode(h_inode)) {
++ xino.h_gen = h_inode->i_generation;
++ WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ }
++ iput(h_inode);
++ }
++#endif
++ arg->err = xino_write(sb, bend, h_ino, &xino);
++ }
++ if (!arg->err)
++ arg->err = append_de(arg->vdir, name, namelen, xino.ino,
++ d_type, arg->delist + bend);
++ } else {
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ for (bindex = 0; bindex < bend; bindex++)
++ if (test_known_wh(arg->whlist + bend, name, namelen))
++ goto out; /* already whiteouted */
++ arg->err = append_wh(arg->whlist + bend, name, namelen, bend);
++ }
++
++ out:
++ if (!arg->err)
++ arg->vdir->vd_jiffy = jiffies;
++ //smp_mb();
++ TraceErr(arg->err);
++ return arg->err;
++}
++
++static int read_vdir(struct file *file, int may_read)
++{
++ int err, do_read, dlgt;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_vdir *vdir, *allocated;
++ unsigned long expire;
++ struct fillvdir_arg arg;
++ aufs_bindex_t bindex, bend, bstart;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, may %d\n", DLNPair(dentry), may_read);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++
++ err = 0;
++ allocated = NULL;
++ do_read = 0;
++ sb = inode->i_sb;
++ expire = stosi(sb)->si_rdcache;
++ vdir = ivdir(inode);
++ if (!vdir) {
++ DEBUG_ON(fvdir_cache(file));
++ do_read = 1;
++ vdir = alloc_vdir();
++ err = PTR_ERR(vdir);
++ if (IS_ERR(vdir))
++ goto out;
++ err = 0;
++ allocated = vdir;
++ } else if (may_read
++ && (inode->i_version != vdir->vd_version
++ || time_after(jiffies, vdir->vd_jiffy + expire))) {
++ LKTRTrace("iver %lu, vdver %lu, exp %lu\n",
++ inode->i_version, vdir->vd_version,
++ vdir->vd_jiffy + expire);
++ do_read = 1;
++ err = reinit_vdir(vdir);
++ if (unlikely(err))
++ goto out;
++ }
++ //DbgVdir(vdir); goto out;
++
++ if (!do_read)
++ return 0; /* success */
++
++ err = -ENOMEM;
++ bend = fbend(file);
++ arg.delist = kmalloc(sizeof(*arg.delist) * (bend + 1), GFP_KERNEL);
++ if (unlikely(!arg.delist))
++ goto out_vdir;
++ arg.whlist = kmalloc(sizeof(*arg.whlist) * (bend + 1), GFP_KERNEL);
++ if (unlikely(!arg.whlist))
++ goto out_delist;
++ err = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ nhash_init(arg.delist + bindex);
++ nhash_init(arg.whlist + bindex);
++ }
++
++ dlgt = need_dlgt(sb);
++ arg.file = file;
++ arg.vdir = vdir;
++ bstart = fbstart(file);
++ for (bindex = bstart; !err && bindex <= bend; bindex++) {
++ struct file *hf;
++ struct inode *h_inode;
++
++ hf = au_h_fptr_i(file, bindex);
++ if (!hf)
++ continue;
++
++ h_inode = hf->f_dentry->d_inode;
++ //hf->f_pos = 0;
++ arg.bindex = bindex;
++ do {
++ arg.err = 0;
++ arg.called = 0;
++ //smp_mb();
++ err = vfsub_readdir(hf, fillvdir, &arg, dlgt);
++ if (err >= 0)
++ err = arg.err;
++ } while (!err && arg.called);
++ }
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ free_dehlist(arg.delist + bindex);
++ nhash_fin(arg.whlist + bindex);
++ }
++ kfree(arg.whlist);
++
++ out_delist:
++ kfree(arg.delist);
++ out_vdir:
++ if (!err) {
++ //file->f_pos = 0;
++ vdir->vd_version = inode->i_version;
++ vdir->vd_last.i = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ if (allocated)
++ set_ivdir(inode, allocated);
++ } else if (allocated)
++ free_vdir(allocated);
++ //DbgVdir(vdir); goto out;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int copy_vdir(struct aufs_vdir *tgt, struct aufs_vdir *src)
++{
++ int err, i, rerr, n;
++
++ TraceEnter();
++ DEBUG_ON(tgt->vd_nblk != 1);
++ //DbgVdir(tgt);
++
++ err = -ENOMEM;
++ if (tgt->vd_nblk < src->vd_nblk) {
++ aufs_deblk_t **p;
++ p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
++ sizeof(*p) * src->vd_nblk, GFP_KERNEL);
++ if (unlikely(!p))
++ goto out;
++ tgt->vd_deblk = p;
++ }
++
++ n = tgt->vd_nblk = src->vd_nblk;
++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AUFS_DEBLK_SIZE);
++ //tgt->vd_last.i = 0;
++ //tgt->vd_last.p.deblk = tgt->vd_deblk[0];
++ tgt->vd_version = src->vd_version;
++ tgt->vd_jiffy = src->vd_jiffy;
++
++ for (i = 1; i < n; i++) {
++ tgt->vd_deblk[i] = kmalloc(AUFS_DEBLK_SIZE, GFP_KERNEL);
++ if (tgt->vd_deblk[i])
++ memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
++ AUFS_DEBLK_SIZE);
++ else
++ goto out;
++ }
++ //smp_mb();
++ //DbgVdir(tgt);
++ return 0; /* success */
++
++ out:
++ rerr = reinit_vdir(tgt);
++ BUG_ON(rerr);
++ TraceErr(err);
++ return err;
++}
++
++int au_init_vdir(struct file *file)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_vdir *vdir_cache, *allocated;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++
++ err = read_vdir(file, !file->f_pos);
++ if (unlikely(err))
++ goto out;
++ //DbgVdir(ivdir(inode)); goto out;
++
++ allocated = NULL;
++ vdir_cache = fvdir_cache(file);
++ if (!vdir_cache) {
++ vdir_cache = alloc_vdir();
++ err = PTR_ERR(vdir_cache);
++ if (IS_ERR(vdir_cache))
++ goto out;
++ allocated = vdir_cache;
++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
++ err = reinit_vdir(vdir_cache);
++ if (unlikely(err))
++ goto out;
++ } else
++ return 0; /* success */
++ //err = 0; DbgVdir(vdir_cache); goto out;
++
++ err = copy_vdir(vdir_cache, ivdir(inode));
++ if (!err) {
++ file->f_version = inode->i_version;
++ if (allocated)
++ set_fvdir_cache(file, allocated);
++ } else if (allocated)
++ free_vdir(allocated);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static loff_t calc_offset(struct aufs_vdir *vdir)
++{
++ loff_t offset;
++ union aufs_deblk_p p;
++
++ p.deblk = vdir->vd_deblk[vdir->vd_last.i];
++ offset = vdir->vd_last.p.p - p.p;
++ offset += sizeof(*p.deblk) * vdir->vd_last.i;
++ return offset;
++}
++
++/* returns true or false */
++static int seek_vdir(struct file *file)
++{
++ int valid, i, n;
++ struct dentry *dentry;
++ struct aufs_vdir *vdir_cache;
++ loff_t offset;
++ union aufs_deblk_p p, deblk_end;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ vdir_cache = fvdir_cache(file);
++ DEBUG_ON(!vdir_cache);
++ //DbgVdir(vdir_cache);
++
++ valid = 1;
++ offset = calc_offset(vdir_cache);
++ LKTRTrace("offset %Ld\n", offset);
++ if (file->f_pos == offset)
++ goto out;
++
++ vdir_cache->vd_last.i = 0;
++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
++ if (!file->f_pos)
++ goto out;
++
++ valid = 0;
++ i = file->f_pos / AUFS_DEBLK_SIZE;
++ LKTRTrace("i %d\n", i);
++ if (i >= vdir_cache->vd_nblk)
++ goto out;
++
++ n = vdir_cache->vd_nblk;
++ //DbgVdir(vdir_cache);
++ for (; i < n; i++) {
++ p.deblk = vdir_cache->vd_deblk[i];
++ deblk_end.deblk = p.deblk + 1;
++ offset = i * AUFS_DEBLK_SIZE;
++ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
++ int l;
++ l = calc_size(p.de->de_str.len);
++ offset += l;
++ p.p += l;
++ }
++ if (!is_deblk_end(&p, &deblk_end)) {
++ valid = 1;
++ vdir_cache->vd_last.i = i;
++ vdir_cache->vd_last.p = p;
++ break;
++ }
++ }
++
++ out:
++ //smp_mb();
++ //DbgVdir(vdir_cache);
++ TraceErr(!valid);
++ return valid;
++}
++
++int au_fill_de(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err, l;
++ struct dentry *dentry;
++ struct aufs_vdir *vdir_cache;
++ struct aufs_de *de;
++ union aufs_deblk_p deblk_end;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ vdir_cache = fvdir_cache(file);
++ DEBUG_ON(!vdir_cache);
++ //DbgVdir(vdir_cache);
++
++ if (!seek_vdir(file))
++ return 0;
++
++ while (1) {
++ deblk_end.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
++ de = vdir_cache->vd_last.p.de;
++ LKTRTrace("%.*s, off%Ld, i%lu, dt%d\n",
++ de->de_str.len, de->de_str.name,
++ file->f_pos, de->de_ino, de->de_type);
++ err = filldir(dirent, de->de_str.name, de->de_str.len,
++ file->f_pos, de->de_ino, de->de_type);
++ if (unlikely(err)) {
++ TraceErr(err);
++ //return err;
++ //todo: ignore the error caused by udba.
++ return 0;
++ }
++
++ l = calc_size(de->de_str.len);
++ vdir_cache->vd_last.p.p += l;
++ file->f_pos += l;
++ }
++ if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
++ vdir_cache->vd_last.i++;
++ vdir_cache->vd_last.p.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
++ file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
++ * vdir_cache->vd_last.i;
++ continue;
++ }
++ break;
++ }
++
++ //smp_mb();
++ return 0;
++}
+diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
+new file mode 100755
+index 0000000..8571d21
+--- /dev/null
++++ b/fs/aufs/vfsub.c
+@@ -0,0 +1,665 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vfsub.c,v 1.5 2007/04/23 00:55:06 sfjro Exp $ */
++// I'm going to slightly mad
++
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++struct permission_args {
++ int *errp;
++ struct inode *inode;
++ int mask;
++ struct nameidata *nd;
++};
++
++static void call_permission(void *args)
++{
++ struct permission_args *a = args;
++ *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
++}
++
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_permission(inode, mask, nd);
++ else {
++ int err;
++ struct permission_args args = {
++ .errp = &err,
++ .inode = inode,
++ .mask = mask,
++ .nd = nd
++ };
++ au_wkq_wait(call_permission, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct create_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++ struct nameidata *nd;
++};
++
++static void call_create(void *args)
++{
++ struct create_args *a = args;
++ *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
++}
++
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_create(dir, dentry, mode, nd);
++ else {
++ int err;
++ struct create_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode,
++ .nd = nd
++ };
++ au_wkq_wait(call_create, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct symlink_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ const char *symname;
++ int mode;
++};
++
++static void call_symlink(void *args)
++{
++ struct symlink_args *a = args;
++ *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
++}
++
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_symlink(dir, dentry, symname, mode);
++ else {
++ int err;
++ struct symlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .symname = symname,
++ .mode = mode
++ };
++ au_wkq_wait(call_symlink, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct mknod_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++ dev_t dev;
++};
++
++static void call_mknod(void *args)
++{
++ struct mknod_args *a = args;
++ *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
++}
++
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_mknod(dir, dentry, mode, dev);
++ else {
++ int err;
++ struct mknod_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode,
++ .dev = dev
++ };
++ au_wkq_wait(call_mknod, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct mkdir_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++};
++
++static void call_mkdir(void *args)
++{
++ struct mkdir_args *a = args;
++ *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
++}
++
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_mkdir(dir, dentry, mode);
++ else {
++ int err;
++ struct mkdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode
++ };
++ au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct link_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *src_dentry, *dentry;
++};
++
++static void call_link(void *args)
++{
++ struct link_args *a = args;
++ *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
++}
++
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_link(src_dentry, dir, dentry);
++ else {
++ int err;
++ struct link_args args = {
++ .errp = &err,
++ .src_dentry = src_dentry,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_link, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct rename_args {
++ int *errp;
++ struct inode *src_dir, *dir;
++ struct dentry *src_dentry, *dentry;
++};
++
++static void call_rename(void *args)
++{
++ struct rename_args *a = args;
++ *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
++ a->dentry);
++}
++
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
++ else {
++ int err;
++ struct rename_args args = {
++ .errp = &err,
++ .src_dir = src_dir,
++ .src_dentry = src_dentry,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_rename, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct rmdir_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++};
++
++static void call_rmdir(void *args)
++{
++ struct rmdir_args *a = args;
++ *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
++}
++
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_rmdir(dir, dentry);
++ else {
++ int err;
++ struct rmdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct read_args {
++ ssize_t *errp;
++ struct file *file;
++ union {
++ void *kbuf;
++ char __user *ubuf;
++ };
++ size_t count;
++ loff_t *ppos;
++};
++
++static void call_read_k(void *args)
++{
++ struct read_args *a = args;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(a->file->f_dentry), (unsigned long)a->count,
++ *a->ppos);
++ *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
++}
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_read_u(file, ubuf, count, ppos);
++ else {
++ ssize_t err, read;
++ struct read_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++
++ if (unlikely(!count))
++ return 0;
++
++ /*
++ * workaround an application bug.
++ * generally, read(2) or write(2) may return the value shorter
++ * than requested. But many applications don't support it,
++ * for example bash.
++ */
++ err = -ENOMEM;
++ if (args.count > PAGE_SIZE)
++ args.count = PAGE_SIZE;
++ args.kbuf = kmalloc(args.count, GFP_KERNEL);
++ if (unlikely(!args.kbuf))
++ goto out;
++
++ read = 0;
++ do {
++ au_wkq_wait(call_read_k, &args, /*dlgt*/1);
++ if (unlikely(err > 0
++ && copy_to_user(ubuf, args.kbuf, err))) {
++ err = -EFAULT;
++ goto out_free;
++ } else if (!err)
++ break;
++ else if (unlikely(err < 0))
++ goto out_free;
++ count -= err;
++ /* do not read too much because of file i/o pointer */
++ if (unlikely(count < args.count))
++ args.count = count;
++ ubuf += err;
++ read += err;
++ } while (count);
++ smp_mb();
++ err = read;
++
++ out_free:
++ kfree(args.kbuf);
++ out:
++ return err;
++ }
++}
++
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_read_k(file, kbuf, count, ppos);
++ else {
++ ssize_t err;
++ struct read_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++ args.kbuf = kbuf;
++ au_wkq_wait(call_read_k, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct write_args {
++ ssize_t *errp;
++ struct file *file;
++ union {
++ void *kbuf;
++ const char __user *ubuf;
++ };
++ void *buf;
++ size_t count;
++ loff_t *ppos;
++};
++
++static void call_write_k(void *args)
++{
++ struct write_args *a = args;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(a->file->f_dentry), (unsigned long)a->count,
++ *a->ppos);
++ *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
++}
++
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_write_u(file, ubuf, count, ppos);
++ else {
++ ssize_t err, written;
++ struct write_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++
++ if (unlikely(!count))
++ return 0;
++
++ /*
++ * workaround an application bug.
++ * generally, read(2) or write(2) may return the value shorter
++ * than requested. But many applications don't support it,
++ * for example bash.
++ */
++ err = -ENOMEM;
++ if (args.count > PAGE_SIZE)
++ args.count = PAGE_SIZE;
++ args.kbuf = kmalloc(args.count, GFP_KERNEL);
++ if (unlikely(!args.kbuf))
++ goto out;
++
++ written = 0;
++ do {
++ if (unlikely(copy_from_user(args.kbuf, ubuf, args.count))) {
++ err = -EFAULT;
++ goto out_free;
++ }
++
++ au_wkq_wait(call_write_k, &args, /*dlgt*/1);
++ if (err > 0) {
++ count -= err;
++ if (count < args.count)
++ args.count = count;
++ ubuf += err;
++ written += err;
++ } else if (!err)
++ break;
++ else if (unlikely(err < 0))
++ goto out_free;
++ } while (count);
++ err = written;
++
++ out_free:
++ kfree(args.kbuf);
++ out:
++ return err;
++ }
++}
++
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_write_k(file, kbuf, count, ppos);
++ else {
++ ssize_t err;
++ struct write_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++ args.kbuf = kbuf;
++ au_wkq_wait(call_write_k, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct readdir_args {
++ int *errp;
++ struct file *file;
++ filldir_t filldir;
++ void *arg;
++};
++
++static void call_readdir(void *args)
++{
++ struct readdir_args *a = args;
++ *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
++}
++
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_readdir(file, filldir, arg);
++ else {
++ int err;
++ struct readdir_args args = {
++ .errp = &err,
++ .file = file,
++ .filldir = filldir,
++ .arg = arg
++ };
++ au_wkq_wait(call_readdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++/* ---------------------------------------------------------------------- */
++
++struct notify_change_args {
++ int *errp;
++ struct dentry *h_dentry;
++ struct iattr *ia;
++};
++
++static void call_notify_change(void *args)
++{
++ struct notify_change_args *a = args;
++ struct inode *h_inode;
++
++ LKTRTrace("%.*s, ia_valid 0x%x\n",
++ DLNPair(a->h_dentry), a->ia->ia_valid);
++ h_inode = a->h_dentry->d_inode;
++ IMustLock(h_inode);
++
++ *a->errp = -EPERM;
++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ lockdep_off();
++ *a->errp = notify_change(a->h_dentry, a->ia);
++ lockdep_on();
++ }
++ TraceErr(*a->errp);
++}
++
++int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt)
++{
++ int err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .h_dentry = dentry,
++ .ia = ia
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_notify_change(&args);
++#else
++ if (!dlgt)
++ call_notify_change(&args);
++ else
++ au_wkq_wait(call_notify_change, &args, /*dlgt*/1);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct unlink_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++};
++
++static void call_unlink(void *args)
++{
++ struct unlink_args *a = args;
++ struct inode *h_inode;
++ const int stop_sillyrename = (au_is_nfs(a->dentry->d_sb)
++ && atomic_read(&a->dentry->d_count) == 1);
++
++ LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
++ DLNPair(a->dentry), stop_sillyrename,
++ atomic_read(&a->dentry->d_count));
++ IMustLock(a->dir);
++
++ if (!stop_sillyrename)
++ dget(a->dentry);
++ h_inode = a->dentry->d_inode;
++ if (h_inode)
++ atomic_inc(&h_inode->i_count);
++#if 0 // partial testing
++ {
++ struct qstr *name = &a->dentry->d_name;
++ if (name->len == sizeof(AUFS_XINO_FNAME) - 1
++ && !strncmp(name->name, AUFS_XINO_FNAME, name->len)) {
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, a->dentry);
++ lockdep_on();
++ } else
++ err = -1;
++ }
++#else
++ // vfs_unlink() locks inode
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, a->dentry);
++ lockdep_on();
++#endif
++
++ if (!stop_sillyrename)
++ dput(a->dentry);
++ if (h_inode)
++ iput(h_inode);
++
++ TraceErr(*a->errp);
++}
++
++/*
++ * @dir: must be locked.
++ * @dentry: target dentry.
++ */
++int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ int err;
++ struct unlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_unlink(&args);
++#else
++ if (!dlgt)
++ call_unlink(&args);
++ else
++ au_wkq_wait(call_unlink, &args, /*dlgt*/1);
++#endif
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct statfs_args {
++ int *errp;
++ void *arg;
++ struct kstatfs *buf;
++};
++
++static void call_statfs(void *args)
++{
++ struct statfs_args *a = args;
++ *a->errp = vfs_statfs(a->arg, a->buf);
++}
++
++int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
++{
++ int err;
++ struct statfs_args args = {
++ .errp = &err,
++ .arg = arg,
++ .buf = buf
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_statfs(&args);
++#else
++ if (!dlgt)
++ call_statfs(&args);
++ else
++ au_wkq_wait(call_statfs, &args, /*dlgt*/1);
++#endif
++ return err;
++}
+diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+new file mode 100755
+index 0000000..52f15cc
+--- /dev/null
++++ b/fs/aufs/vfsub.h
+@@ -0,0 +1,427 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vfsub.h,v 1.8 2007/05/14 03:39:10 sfjro Exp $ */
++
++#ifndef __AUFS_VFSUB_H__
++#define __AUFS_VFSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include "wkq.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* simple abstractions, for future use */
++static inline
++int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
++{
++ LKTRTrace("i%lu, mask 0x%x, nd %p\n", inode->i_ino, mask, nd);
++#if 0
++#else
++ return permission(inode, mask, nd);
++#endif
++}
++
++static inline
++struct file *vfsub_filp_open(const char *path, int oflags, int mode)
++{
++ struct file *err;
++
++ LKTRTrace("%s\n", path);
++
++ lockdep_off();
++ err = filp_open(path, oflags, mode);
++ lockdep_on();
++ return err;
++}
++
++static inline
++int vfsub_path_lookup(const char *name, unsigned int flags,
++ struct nameidata *nd)
++{
++ int err;
++
++ LKTRTrace("%s\n", name);
++
++ //lockdep_off();
++ err = path_lookup(name, flags, nd);
++ //lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_create(dir, dentry, mode, nd);
++#endif
++}
++
++static inline
++int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname, int mode)
++{
++ LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
++ dir->i_ino, DLNPair(dentry), symname, mode);
++#if 0
++#else
++ return vfs_symlink(dir, dentry, symname, mode);
++#endif
++}
++
++static inline
++int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
++ dev_t dev)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_mknod(dir, dentry, mode, dev);
++#endif
++}
++
++static inline
++int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("%.*s, i%lu, %.*s\n",
++ DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_link(src_dentry, dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
++ src_dir->i_ino, DLNPair(src_dentry),
++ dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_rename(src_dir, src_dentry, dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_mkdir(dir, dentry, mode);
++#endif
++}
++
++static inline int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_rmdir(dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)count, *ppos);
++
++ /* nfs uses some locks */
++ lockdep_off();
++#if 0
++#else
++ err = vfs_read(file, ubuf, count, ppos);
++#endif
++ lockdep_on();
++ return err;
++}
++
++// kernel_read() ??
++static inline
++ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = do_vfsub_read_u(file, (char __user*)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++static inline
++ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)count, *ppos);
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_write(file, ubuf, count, ppos);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = do_vfsub_write_u(file, (const char __user*)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++static inline
++int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
++{
++ int err;
++
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_readdir(file, filldir, arg);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
++{
++ loff_t err;
++
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_llseek(file, offset, origin);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++static inline int need_dlgt(struct super_block *sb)
++{
++ return (au_flag_test(sb, AuFlag_DLGT) && !is_au_wkq(current));
++}
++
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt);
++
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt);
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt);
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt);
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt);
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt);
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt);
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt);
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt);
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt);
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt);
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt);
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
++
++#else
++
++static inline int need_dlgt(struct super_block *sb)
++{
++ return 0;
++}
++
++static inline
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt)
++{
++ return do_vfsub_permission(inode, mask, nd);
++}
++
++static inline
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt)
++{
++ return do_vfsub_create(dir, dentry, mode, nd);
++}
++
++static inline
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt)
++{
++ return do_vfsub_symlink(dir, dentry, symname, mode);
++}
++
++static inline
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt)
++{
++ return do_vfsub_mknod(dir, dentry, mode, dev);
++}
++
++static inline
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_link(src_dentry, dir, dentry);
++}
++
++static inline
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
++}
++
++static inline
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
++ int dlgt)
++{
++ return do_vfsub_mkdir(dir, dentry, mode);
++}
++
++static inline
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_rmdir(dir, dentry);
++}
++
++static inline
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ return do_vfsub_read_u(file, ubuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ return do_vfsub_read_k(file, kbuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ return do_vfsub_write_u(file, ubuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ return do_vfsub_write_k(file, kbuf, count, ppos);
++}
++
++static inline
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
++{
++ return do_vfsub_readdir(file, filldir, arg);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
++{
++ struct dentry *d;
++
++ lockdep_off();
++ d = lock_rename(d1, d2);
++ lockdep_on();
++ return d;
++}
++
++static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
++{
++ lockdep_off();
++ unlock_rename(d1, d2);
++ lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt);
++int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt);
++int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_VFSUB_H__ */
+diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c
+new file mode 100755
+index 0000000..b7f874c
+--- /dev/null
++++ b/fs/aufs/whout.c
+@@ -0,0 +1,933 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: whout.c,v 1.14 2007/05/14 03:40:40 sfjro Exp $ */
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/random.h>
++#include <linux/security.h>
++#include "aufs.h"
++
++#define WH_MASK S_IRUGO
++
++/* If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++static struct qstr diropq_name = {
++ .name = AUFS_WH_DIROPQ,
++ .len = sizeof(AUFS_WH_DIROPQ) - 1
++};
++
++/*
++ * generate whiteout name, which is NOT terminated by NULL.
++ * @name: original d_name.name
++ * @len: original d_name.len
++ * @wh: whiteout qstr
++ * returns zero when succeeds, otherwise error.
++ * succeeded value as wh->name should be freed by au_free_whname().
++ */
++int au_alloc_whname(const char *name, int len, struct qstr *wh)
++{
++ char *p;
++
++ DEBUG_ON(!name || !len || !wh);
++
++ if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
++ return -ENAMETOOLONG;
++
++ wh->len = len + AUFS_WH_PFX_LEN;
++ wh->name = p = kmalloc(wh->len, GFP_KERNEL);
++ //if (LktrCond) {kfree(p); wh->name = p = NULL;}
++ if (p) {
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ memcpy(p + AUFS_WH_PFX_LEN, name, len);
++ //smp_mb();
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++void au_free_whname(struct qstr *wh)
++{
++ DEBUG_ON(!wh || !wh->name);
++ kfree(wh->name);
++#ifdef CONFIG_AUFS_DEBUG
++ wh->name = NULL;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the @wh_name exists under @hidden_parent.
++ * @try_sio specifies the necessary of super-io.
++ */
++int is_wh(struct dentry *hidden_parent, struct qstr *wh_name, int try_sio,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct dentry *wh_dentry;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(hidden_parent),
++ wh_name->len, wh_name->name, lkup->nfsmnt, lkup->dlgt);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ if (!try_sio)
++ wh_dentry = lkup_one(wh_name->name, hidden_parent,
++ wh_name->len, lkup);
++ else
++ wh_dentry = sio_lkup_one(wh_name->name, hidden_parent,
++ wh_name->len, lkup);
++ //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ err = 0;
++ if (!wh_dentry->d_inode)
++ goto out_wh; /* success */
++
++ err = 1;
++ if (S_ISREG(wh_dentry->d_inode->i_mode))
++ goto out_wh; /* success */
++
++ err = -EIO;
++ IOErr("%.*s Invalid whiteout entry type 0%o.\n",
++ DLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * test if the @hidden_dentry sets opaque or not.
++ */
++int is_diropq(struct dentry *hidden_dentry, struct lkup_args *lkup)
++{
++ int err;
++ struct inode *hidden_dir;
++
++ LKTRTrace("dentry %.*s\n", DLNPair(hidden_dentry));
++ hidden_dir = hidden_dentry->d_inode;
++ DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ err = is_wh(hidden_dentry, &diropq_name, /*try_sio*/1, lkup);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns a negative dentry whose name is unique and temporary.
++ */
++struct dentry *lkup_whtmp(struct dentry *hidden_parent, struct qstr *prefix,
++ struct lkup_args *lkup)
++{
++#define HEX_LEN 4
++ struct dentry *dentry;
++ int len, i;
++ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
++ + HEX_LEN + 1], *name, *p;
++ static unsigned char cnt;
++
++ LKTRTrace("hp %.*s, prefix %.*s\n",
++ DLNPair(hidden_parent), prefix->len, prefix->name);
++ DEBUG_ON(!hidden_parent->d_inode);
++ IMustLock(hidden_parent->d_inode);
++
++ name = defname;
++ len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
++ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
++ dentry = ERR_PTR(-ENAMETOOLONG);
++ if (unlikely(len >= PATH_MAX))
++ goto out;
++ dentry = ERR_PTR(-ENOMEM);
++ name = kmalloc(len + 1, GFP_KERNEL);
++ //if (LktrCond) {kfree(name); name = NULL;}
++ if (unlikely(!name))
++ goto out;
++ }
++
++ // doubly whiteout-ed
++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
++ p = name + AUFS_WH_PFX_LEN * 2;
++ memcpy(p, prefix->name, prefix->len);
++ p += prefix->len;
++ *p++ = '.';
++ DEBUG_ON(name + len + 1 - p <= HEX_LEN);
++
++ for (i = 0; i < 3; i++) {
++ sprintf(p, "%.*d", HEX_LEN, cnt++);
++ dentry = sio_lkup_one(name, hidden_parent, len, lkup);
++ //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
++ if (unlikely(IS_ERR(dentry) || !dentry->d_inode))
++ goto out_name;
++ dput(dentry);
++ }
++ //Warn("could not get random name\n");
++ dentry = ERR_PTR(-EEXIST);
++ Dbg("%.*s\n", len, name);
++ BUG();
++
++ out_name:
++ if (unlikely(name != defname))
++ kfree(name);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++#undef HEX_LEN
++}
++
++/*
++ * rename the @dentry of @bindex to the whiteouted temporary name.
++ */
++int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct inode *hidden_dir;
++ struct dentry *hidden_dentry, *hidden_parent, *tmp_dentry;
++ struct super_block *sb;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry || !hidden_dentry->d_inode);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ sb = dentry->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = need_dlgt(sb);
++ tmp_dentry = lkup_whtmp(hidden_parent, &hidden_dentry->d_name, &lkup);
++ //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(tmp_dentry);
++ if (!IS_ERR(tmp_dentry)) {
++ /* under the same dir, no need to lock_rename() */
++ err = vfsub_rename(hidden_dir, hidden_dentry,
++ hidden_dir, tmp_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1; //unavailable
++ TraceErr(err);
++ dput(tmp_dentry);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_unlink_wh_dentry(struct inode *hidden_dir, struct dentry *wh_dentry,
++ struct dentry *dentry, int dlgt)
++{
++ int err;
++
++ LKTRTrace("hi%lu, wh %.*s, d %p\n", hidden_dir->i_ino,
++ DLNPair(wh_dentry), dentry);
++ DEBUG_ON((dentry && dbwh(dentry) == -1)
++ || !wh_dentry->d_inode
++ || !S_ISREG(wh_dentry->d_inode->i_mode));
++ IMustLock(hidden_dir);
++
++ err = vfsub_unlink(hidden_dir, wh_dentry, dlgt);
++ //if (LktrCond) err = -1; // unavailable
++ if (!err && dentry)
++ set_dbwh(dentry, -1);
++
++ TraceErr(err);
++ return err;
++}
++
++static int unlink_wh_name(struct dentry *hidden_parent, struct qstr *wh,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct inode *hidden_dir;
++ struct dentry *hidden_dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(wh));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ // au_test_perm() is already done
++ hidden_dentry = lkup_one(wh->name, hidden_parent, wh->len, lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ if (!IS_ERR(hidden_dentry)) {
++ err = 0;
++ if (hidden_dentry->d_inode)
++ err = vfsub_unlink(hidden_dir, hidden_dentry,
++ lkup->dlgt);
++ dput(hidden_dentry);
++ } else
++ err = PTR_ERR(hidden_dentry);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void clean_wh(struct inode *h_dir, struct dentry *wh)
++{
++ TraceEnter();
++ if (wh->d_inode) {
++ int err = vfsub_unlink(h_dir, wh, /*dlgt*/0);
++ if (unlikely(err))
++ Warn("failed unlink %.*s (%d), ignored.\n",
++ DLNPair(wh), err);
++ }
++}
++
++static void clean_plink(struct inode *h_dir, struct dentry *plink)
++{
++ TraceEnter();
++ if (plink->d_inode) {
++ int err = vfsub_rmdir(h_dir, plink, /*dlgt*/0);
++ if (unlikely(err))
++ Warn("failed rmdir %.*s (%d), ignored.\n",
++ DLNPair(plink), err);
++ }
++}
++
++static int test_linkable(struct inode *h_dir)
++{
++ if (h_dir->i_op && h_dir->i_op->link)
++ return 0;
++ return -ENOSYS;
++}
++
++static int plink_dir(struct inode *h_dir, struct dentry *plink)
++{
++ int err;
++
++ err = -EEXIST;
++ if (!plink->d_inode) {
++ int mode = S_IRWXU;
++ if (unlikely(au_is_nfs(plink->d_sb)))
++ mode |= S_IXUGO;
++ err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
++ } else if (S_ISDIR(plink->d_inode->i_mode))
++ err = 0;
++ else
++ Err("unknown %.*s exists\n", DLNPair(plink));
++
++ return err;
++}
++
++/*
++ * initialize the whiteout base file/dir for @br.
++ */
++int init_wh(struct dentry *h_root, struct aufs_branch *br,
++ struct vfsmount *nfsmnt, struct super_block *sb)
++{
++ int err;
++ struct dentry *wh, *plink;
++ struct inode *h_dir;
++ static struct qstr base_name[] = {
++ {.name = AUFS_WH_BASENAME, .len = sizeof(AUFS_WH_BASENAME) - 1},
++ {.name = AUFS_WH_PLINKDIR, .len = sizeof(AUFS_WH_PLINKDIR) - 1}
++ };
++ struct lkup_args lkup = {
++ .nfsmnt = nfsmnt,
++ .dlgt = 0 // always no dlgt
++ };
++ const int do_plink = au_flag_test(sb, AuFlag_PLINK);
++
++ LKTRTrace("nfsmnt %p\n", nfsmnt);
++ BrWhMustWriteLock(br);
++ SiMustWriteLock(sb);
++ h_dir = h_root->d_inode;
++ IMustLock(h_dir);
++
++ // doubly whiteouted
++ wh = lkup_wh(h_root, base_name + 0, &lkup);
++ //if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
++ err = PTR_ERR(wh);
++ if (IS_ERR(wh))
++ goto out;
++ DEBUG_ON(br->br_wh && br->br_wh != wh);
++
++ plink = lkup_wh(h_root, base_name + 1, &lkup);
++ err = PTR_ERR(plink);
++ if (IS_ERR(plink))
++ goto out_dput_wh;
++ DEBUG_ON(br->br_plink && br->br_plink != plink);
++
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++
++ err = 0;
++ switch (br->br_perm) {
++ case AuBr_RR:
++ case AuBr_RO:
++ case AuBr_RRWH:
++ case AuBr_ROWH:
++ clean_wh(h_dir, wh);
++ clean_plink(h_dir, plink);
++ break;
++
++ case AuBr_RWNoLinkWH:
++ clean_wh(h_dir, wh);
++ if (do_plink) {
++ err = test_linkable(h_dir);
++ if (unlikely(err))
++ goto out_nolink;
++
++ err = plink_dir(h_dir, plink);
++ if (unlikely(err))
++ goto out_err;
++ br->br_plink = dget(plink);
++ } else
++ clean_plink(h_dir, plink);
++ break;
++
++ case AuBr_RW:
++ /*
++ * for the moment, aufs supports the branch filesystem
++ * which does not support link(2).
++ * testing on FAT which does not support i_op->setattr() fully either,
++ * copyup failed.
++ * finally, such filesystem will not be used as the writable branch.
++ */
++ err = test_linkable(h_dir);
++ if (unlikely(err))
++ goto out_nolink;
++
++ err = -EEXIST;
++ if (!wh->d_inode)
++ err = vfsub_create(h_dir, wh, WH_MASK, NULL, /*dlgt*/0);
++ else if (S_ISREG(wh->d_inode->i_mode))
++ err = 0;
++ else
++ Err("unknown %.*s/%.*s exists\n",
++ DLNPair(h_root), DLNPair(wh));
++ if (unlikely(err))
++ goto out_err;
++
++ if (do_plink) {
++ err = plink_dir(h_dir, plink);
++ if (unlikely(err))
++ goto out_err;
++ br->br_plink = dget(plink);
++ } else
++ clean_plink(h_dir, plink);
++ br->br_wh = dget(wh);
++ break;
++
++ default:
++ BUG();
++ }
++
++ out_dput:
++ dput(plink);
++ out_dput_wh:
++ dput(wh);
++ out:
++ TraceErr(err);
++ return err;
++ out_nolink:
++ Err("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
++ DLNPair(h_root));
++ goto out_dput;
++ out_err:
++ Err("an error(%d) on the writable branch %.*s(%s)\n",
++ err, DLNPair(h_root), au_sbtype(h_root->d_sb));
++ goto out_dput;
++}
++
++struct reinit_br_wh {
++ struct super_block *sb;
++ struct aufs_branch *br;
++};
++
++static void reinit_br_wh(void *arg)
++{
++ int err;
++ struct reinit_br_wh *a = arg;
++ struct inode *hidden_dir, *dir;
++ struct dentry *hidden_root;
++ aufs_bindex_t bindex;
++
++ TraceEnter();
++ DEBUG_ON(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
++
++ err = 0;
++ /* big lock */
++ si_write_lock(a->sb);
++ if (unlikely(!br_writable(a->br->br_perm)))
++ goto out;
++ bindex = find_brindex(a->sb, a->br->br_id);
++ if (unlikely(bindex < 0))
++ goto out;
++
++ dir = a->sb->s_root->d_inode;
++ hidden_root = a->br->br_wh->d_parent;
++ hidden_dir = hidden_root->d_inode;
++ DEBUG_ON(!hidden_dir->i_op || !hidden_dir->i_op->link);
++ hdir_lock(hidden_dir, dir, bindex);
++ br_wh_write_lock(a->br);
++ err = vfsub_unlink(hidden_dir, a->br->br_wh, /*dlgt*/0);
++ //if (LktrCond) err = -1;
++ dput(a->br->br_wh);
++ a->br->br_wh = NULL;
++ if (!err)
++ err = init_wh(hidden_root, a->br, au_do_nfsmnt(a->br->br_mnt),
++ a->sb);
++ br_wh_write_unlock(a->br);
++ hdir_unlock(hidden_dir, dir, bindex);
++
++ out:
++ atomic_dec(&a->br->br_wh_running);
++ br_put(a->br);
++ si_write_unlock(a->sb);
++ au_mntput(a->sb);
++ kfree(arg);
++ if (unlikely(err))
++ IOErr("err %d\n", err);
++}
++
++static void kick_reinit_br_wh(struct super_block *sb, struct aufs_branch *br)
++{
++ int do_dec;
++ struct reinit_br_wh *arg;
++
++ do_dec = 1;
++ if (atomic_inc_return(&br->br_wh_running) != 1)
++ goto out;
++
++ // ignore ENOMEM
++ arg = kmalloc(sizeof(*arg), GFP_KERNEL);
++ if (arg) {
++ // dec(wh_running), kfree(arg) and br_put() in reinit function
++ arg->sb = sb;
++ arg->br = br;
++ br_get(br);
++ /* prohibit umount */
++ au_mntget(sb);
++ au_wkq_nowait(reinit_br_wh, arg, /*dlgt*/0);
++ do_dec = 0;
++ }
++
++ out:
++ if (do_dec)
++ atomic_dec(&br->br_wh_running);
++}
++
++/*
++ * create the whiteoute @wh.
++ */
++static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ int err, dlgt;
++ struct aufs_branch *br;
++ struct dentry *hidden_parent;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%.*s\n", DLNPair(wh));
++ SiMustReadLock(sb);
++ hidden_parent = wh->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ dlgt = need_dlgt(sb);
++ br = stobr(sb, bindex);
++ br_wh_read_lock(br);
++ if (br->br_wh) {
++ err = vfsub_link(br->br_wh, hidden_dir, wh, dlgt);
++ if (!err || err != -EMLINK)
++ goto out;
++
++ // link count full. re-initialize br_wh.
++ kick_reinit_br_wh(sb, br);
++ }
++
++ // return this error in this context
++ err = vfsub_create(hidden_dir, wh, WH_MASK, NULL, dlgt);
++
++ out:
++ br_wh_read_unlock(br);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create or remove the diropq.
++ */
++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt)
++{
++ struct dentry *opq_dentry, *hidden_dentry;
++ struct inode *hidden_dir;
++ int err;
++ struct super_block *sb;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, bindex %d, do_create %d\n", DLNPair(dentry),
++ bindex, do_create);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_dir = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ // already checked by au_test_perm().
++ sb = dentry->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = dlgt;
++ opq_dentry = lkup_one(diropq_name.name, hidden_dentry, diropq_name.len,
++ &lkup);
++ //if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
++ if (IS_ERR(opq_dentry))
++ goto out;
++
++ if (do_create) {
++ DEBUG_ON(opq_dentry->d_inode);
++ err = link_or_create_wh(opq_dentry, sb, bindex);
++ //if (LktrCond) {vfs_unlink(hidden_dir, opq_dentry); err = -1;}
++ if (!err) {
++ set_dbdiropq(dentry, bindex);
++ goto out; /* success */
++ }
++ } else {
++ DEBUG_ON(/* !S_ISDIR(dentry->d_inode->i_mode)
++ * || */!opq_dentry->d_inode);
++ err = vfsub_unlink(hidden_dir, opq_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1;
++ if (!err)
++ set_dbdiropq(dentry, -1);
++ }
++ dput(opq_dentry);
++ opq_dentry = ERR_PTR(err);
++
++ out:
++ TraceErrPtr(opq_dentry);
++ return opq_dentry;
++}
++
++struct do_diropq_args {
++ struct dentry **errp;
++ struct dentry *dentry;
++ aufs_bindex_t bindex;
++ int do_create, dlgt;
++};
++
++static void call_do_diropq(void *args)
++{
++ struct do_diropq_args *a = args;
++ *a->errp = do_diropq(a->dentry, a->bindex, a->do_create, a->dlgt);
++}
++
++struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt)
++{
++ struct dentry *diropq, *hidden_dentry;
++
++ LKTRTrace("%.*s, bindex %d, do_create %d\n",
++ DLNPair(dentry), bindex, do_create);
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!au_test_perm(hidden_dentry->d_inode, MAY_EXEC | MAY_WRITE, dlgt))
++ diropq = do_diropq(dentry, bindex, do_create, dlgt);
++ else {
++ struct do_diropq_args args = {
++ .errp = &diropq,
++ .dentry = dentry,
++ .bindex = bindex,
++ .do_create = do_create,
++ .dlgt = dlgt
++ };
++ au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
++ }
++
++ TraceErrPtr(diropq);
++ return diropq;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * lookup whiteout dentry.
++ * @hidden_parent: hidden parent dentry which must exist and be locked
++ * @base_name: name of dentry which will be whiteouted
++ * returns dentry for whiteout.
++ */
++struct dentry *lkup_wh(struct dentry *hidden_parent, struct qstr *base_name,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct qstr wh_name;
++ struct dentry *wh_dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(base_name));
++ IMustLock(hidden_parent->d_inode);
++
++ err = au_alloc_whname(base_name->name, base_name->len, &wh_name);
++ //if (LktrCond) {au_free_whname(&wh_name); err = -1;}
++ wh_dentry = ERR_PTR(err);
++ if (!err) {
++ // do not superio.
++ wh_dentry = lkup_one(wh_name.name, hidden_parent, wh_name.len,
++ lkup);
++ au_free_whname(&wh_name);
++ }
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/*
++ * link/create a whiteout for @dentry on @bindex.
++ */
++struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *hidden_parent,
++ struct lkup_args *lkup)
++{
++ struct dentry *wh_dentry;
++ int err;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s/%.*s on b%d\n", DLNPair(hidden_parent),
++ DLNPair(dentry), bindex);
++
++ sb = dentry->d_sb;
++ wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, lkup);
++ //au_nfsmnt(sb, bindex), need_dlgt(sb));
++ //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
++ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
++ IMustLock(hidden_parent->d_inode);
++ err = link_or_create_wh(wh_dentry, sb, bindex);
++ if (!err)
++ set_dbwh(dentry, bindex);
++ else {
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(err);
++ }
++ }
++
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Delete all whiteouts in this directory in branch bindex. */
++static int del_wh_children(struct aufs_nhash *whlist,
++ struct dentry *hidden_parent, aufs_bindex_t bindex,
++ struct lkup_args *lkup)
++{
++ int err, i;
++ struct qstr wh_name;
++ char *p;
++ struct inode *hidden_dir;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", DLNPair(hidden_parent));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ DEBUG_ON(IS_RDONLY(hidden_dir));
++ //SiMustReadLock(??);
++
++ err = -ENOMEM;
++ wh_name.name = p = __getname();
++ //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
++ if (unlikely(!wh_name.name))
++ goto out;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++
++ // already checked by au_test_perm().
++ err = 0;
++ for (i = 0; !err && i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ if (tpos->wh_bindex != bindex)
++ continue;
++ str = &tpos->wh_str;
++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
++ memcpy(p, str->name, str->len);
++ wh_name.len = AUFS_WH_PFX_LEN + str->len;
++ err = unlink_wh_name(hidden_parent, &wh_name,
++ lkup);
++ //if (LktrCond) err = -1;
++ if (!err)
++ continue;
++ break;
++ }
++ IOErr("whiteout name too long %.*s\n",
++ str->len, str->name);
++ err = -EIO;
++ break;
++ }
++ }
++ __putname(wh_name.name);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct del_wh_children_args {
++ int *errp;
++ struct aufs_nhash *whlist;
++ struct dentry *hidden_parent;
++ aufs_bindex_t bindex;
++ struct lkup_args *lkup;
++};
++
++static void call_del_wh_children(void *args)
++{
++ struct del_wh_children_args *a = args;
++ *a->errp = del_wh_children(a->whlist, a->hidden_parent, a->bindex,
++ a->lkup);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * rmdir the whiteouted temporary named dir @hidden_dentry.
++ * @whlist: whiteouted children.
++ */
++int rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir, struct inode *inode)
++{
++ int err;
++ struct inode *hidden_inode, *hidden_dir;
++ struct lkup_args lkup;
++ struct super_block *sb;
++
++ LKTRTrace("hd %.*s, b%d, i%lu\n",
++ DLNPair(hidden_dentry), bindex, dir->i_ino);
++ IMustLock(dir);
++ IiMustAnyLock(dir);
++ hidden_dir = hidden_dentry->d_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ sb = inode->i_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = need_dlgt(sb);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(hidden_inode != au_h_iptr_i(inode, bindex));
++ hdir2_lock(hidden_inode, inode, bindex);
++ if (!au_test_perm(hidden_inode, MAY_EXEC | MAY_WRITE, lkup.dlgt))
++ err = del_wh_children(whlist, hidden_dentry, bindex, &lkup);
++ else {
++ // ugly
++ int dlgt = lkup.dlgt;
++ struct del_wh_children_args args = {
++ .errp = &err,
++ .whlist = whlist,
++ .hidden_parent = hidden_dentry,
++ .bindex = bindex,
++ .lkup = &lkup
++ };
++
++ lkup.dlgt = 0;
++ au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
++ lkup.dlgt = dlgt;
++ }
++ hdir_unlock(hidden_inode, inode, bindex);
++
++ if (!err) {
++ err = vfsub_rmdir(hidden_dir, hidden_dentry, lkup.dlgt);
++ //d_drop(hidden_dentry);
++ //if (LktrCond) err = -1;
++ }
++
++ if (!err) {
++ if (ibstart(dir) == bindex) {
++ au_cpup_attr_timesizes(dir);
++ //au_cpup_attr_nlink(dir);
++ dir->i_nlink--;
++ }
++ return 0; /* success */
++ }
++
++ Warn("failed removing %.*s(%d), ignored\n",
++ DLNPair(hidden_dentry), err);
++ return err;
++}
++
++static void do_rmdir_whtmp(void *arg)
++{
++ int err;
++ struct rmdir_whtmp_arg *a = arg;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, b%d, dir i%lu\n",
++ DLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
++
++ i_lock(a->dir);
++ sb = a->dir->i_sb;
++ si_read_lock(sb);
++ err = test_ro(sb, a->bindex, NULL);
++ if (!err) {
++ struct inode *hidden_dir = a->h_dentry->d_parent->d_inode;
++
++ ii_write_lock_child(a->inode);
++ ii_write_lock_parent(a->dir);
++ hdir_lock(hidden_dir, a->dir, a->bindex);
++ err = rmdir_whtmp(a->h_dentry, &a->whlist, a->bindex,
++ a->dir, a->inode);
++ hdir_unlock(hidden_dir, a->dir, a->bindex);
++ ii_write_unlock(a->dir);
++ ii_write_unlock(a->inode);
++ }
++ dput(a->h_dentry);
++ nhash_fin(&a->whlist);
++ iput(a->inode);
++ si_read_unlock(sb);
++ au_mntput(sb);
++ i_unlock(a->dir);
++ iput(a->dir);
++ kfree(arg);
++ if (unlikely(err))
++ IOErr("err %d\n", err);
++}
++
++void kick_rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir,
++ struct inode *inode, struct rmdir_whtmp_arg *arg)
++{
++ LKTRTrace("%.*s\n", DLNPair(hidden_dentry));
++ IMustLock(dir);
++
++ // all post-process will be done in do_rmdir_whtmp().
++ arg->h_dentry = dget(hidden_dentry);
++ nhash_init(&arg->whlist);
++ nhash_move(&arg->whlist, whlist);
++ arg->bindex = bindex;
++ arg->dir = igrab(dir);
++ arg->inode = igrab(inode);
++ /* prohibit umount */
++ au_mntget(dir->i_sb);
++
++ au_wkq_nowait(do_rmdir_whtmp, arg, /*dlgt*/0);
++}
+diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h
+new file mode 100755
+index 0000000..d44c3cd
+--- /dev/null
++++ b/fs/aufs/whout.h
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: whout.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_WHOUT_H__
++#define __AUFS_WHOUT_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++
++int au_alloc_whname(const char *name, int len, struct qstr *wh);
++void au_free_whname(struct qstr *wh);
++
++struct lkup_args;
++int is_wh(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
++ struct lkup_args *lkup);
++int is_diropq(struct dentry *h_dentry, struct lkup_args *lkup);
++
++struct dentry *lkup_whtmp(struct dentry *h_parent, struct qstr *prefix,
++ struct lkup_args *lkup);
++int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex);
++int au_unlink_wh_dentry(struct inode *h_dir, struct dentry *wh_dentry,
++ struct dentry *dentry, int dlgt);
++
++struct aufs_branch;
++int init_wh(struct dentry *h_parent, struct aufs_branch *br,
++ struct vfsmount *nfsmnt, struct super_block *sb);
++
++struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt);
++
++struct dentry *lkup_wh(struct dentry *h_parent, struct qstr *base_name,
++ struct lkup_args *lkup);
++struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent,
++ struct lkup_args *lkup);
++
++/* real rmdir the whiteout-ed dir */
++struct rmdir_whtmp_arg {
++ struct dentry *h_dentry;
++ struct aufs_nhash whlist;
++ aufs_bindex_t bindex;
++ struct inode *dir, *inode;
++};
++
++struct aufs_nhash;
++int rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir, struct inode *inode);
++void kick_rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir,
++ struct inode *inode, struct rmdir_whtmp_arg *arg);
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++struct dentry *create_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int dlgt)
++{
++ return sio_diropq(dentry, bindex, 1, dlgt);
++}
++
++static inline
++int remove_diropq(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
++{
++ return PTR_ERR(sio_diropq(dentry, bindex, 0, dlgt));
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WHOUT_H__ */
+diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c
+new file mode 100755
+index 0000000..b5ab023
+--- /dev/null
++++ b/fs/aufs/wkq.c
+@@ -0,0 +1,283 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: wkq.c,v 1.14 2007/05/14 03:39:10 sfjro Exp $ */
++
++#include <linux/module.h>
++#include "aufs.h"
++
++struct au_wkq *au_wkq;
++
++struct au_cred {
++#ifdef CONFIG_AUFS_DLGT
++ uid_t fsuid;
++ gid_t fsgid;
++ kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
++ //unsigned keep_capabilities:1;
++ //struct user_struct *user;
++ //struct fs_struct *fs;
++ //struct nsproxy *nsproxy;
++#endif
++};
++
++struct au_wkinfo {
++ struct work_struct wk;
++
++ unsigned int wait:1;
++ unsigned int dlgt:1;
++ struct au_cred cred;
++
++ au_wkq_func_t func;
++ void *args;
++
++ atomic_t *busyp;
++ struct completion *comp;
++};
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++static void cred_store(struct au_cred *cred)
++{
++ cred->fsuid = current->fsuid;
++ cred->fsgid = current->fsgid;
++ cred->cap_effective = current->cap_effective;
++ cred->cap_inheritable = current->cap_inheritable;
++ cred->cap_permitted = current->cap_permitted;
++}
++
++static void cred_revert(struct au_cred *cred)
++{
++ DEBUG_ON(!is_au_wkq(current));
++ current->fsuid = cred->fsuid;
++ current->fsgid = cred->fsgid;
++ current->cap_effective = cred->cap_effective;
++ current->cap_inheritable = cred->cap_inheritable;
++ current->cap_permitted = cred->cap_permitted;
++}
++
++static void cred_switch(struct au_cred *old, struct au_cred *new)
++{
++ cred_store(old);
++ cred_revert(new);
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++#ifdef CONFIG_AUFS_SYSAUFS
++ unsigned int new, old;
++
++ do {
++ new = atomic_read(wkinfo->busyp);
++ old = wkq->max_busy;
++ if (new <= old)
++ break;
++ } while (cmpxchg(&wkq->max_busy, old, new) == old);
++#endif
++}
++
++static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++ wkinfo->busyp = &wkq->busy;
++ update_busy(wkq, wkinfo);
++ if (wkinfo->wait)
++ return !queue_work(wkq->q, &wkinfo->wk);
++ else
++ return !schedule_work(&wkinfo->wk);
++}
++
++static void do_wkq(struct au_wkinfo *wkinfo)
++{
++ unsigned int idle, n;
++ int i, idle_idx;
++
++ TraceEnter();
++
++ while (1) {
++ if (wkinfo->wait) {
++ idle_idx = 0;
++ idle = UINT_MAX;
++ for (i = 0; i < aufs_nwkq; i++) {
++ n = atomic_inc_return(&au_wkq[i].busy);
++ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
++ return; /* success */
++
++ if (n < idle) {
++ idle_idx = i;
++ idle = n;
++ }
++ atomic_dec(&au_wkq[i].busy);
++ }
++ } else
++ idle_idx = aufs_nwkq;
++
++ atomic_inc(&au_wkq[idle_idx].busy);
++ if (!enqueue(au_wkq + idle_idx, wkinfo))
++ return; /* success */
++
++ /* impossible? */
++ Warn1("failed to queue_work()\n");
++ yield();
++ }
++}
++
++static AuWkqFunc(wkq_func, wk)
++{
++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
++
++ LKTRTrace("wkinfo{%u, %u, %p, %p, %p}\n",
++ wkinfo->wait, wkinfo->dlgt, wkinfo->func, wkinfo->busyp,
++ wkinfo->comp);
++#ifdef CONFIG_AUFS_DLGT
++ if (!wkinfo->dlgt)
++ wkinfo->func(wkinfo->args);
++ else {
++ struct au_cred cred;
++ cred_switch(&cred, &wkinfo->cred);
++ wkinfo->func(wkinfo->args);
++ cred_revert(&cred);
++ }
++#else
++ wkinfo->func(wkinfo->args);
++#endif
++ atomic_dec(wkinfo->busyp);
++ if (wkinfo->wait)
++ complete(wkinfo->comp);
++ else {
++ kfree(wkinfo);
++ module_put(THIS_MODULE);
++ }
++}
++
++void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait)
++{
++ DECLARE_COMPLETION_ONSTACK(comp);
++ struct au_wkinfo _wkinfo = {
++ .wait = 1,
++ .dlgt = !!dlgt,
++ .func = func,
++ .args = args,
++ .comp = &comp
++ }, *wkinfo = &_wkinfo;
++
++ LKTRTrace("dlgt %d, do_wait %d\n", dlgt, do_wait);
++ DEBUG_ON(is_au_wkq(current));
++
++ if (unlikely(!do_wait)) {
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ /*
++ * never fail.
++ * wkq_func() must free this wkinfo.
++ * it highly depends upon the implementation of workqueue.
++ */
++ wait_event(wq, (wkinfo = kmalloc(sizeof(*wkinfo), GFP_KERNEL)));
++ wkinfo->wait = 0;
++ wkinfo->dlgt = !!dlgt;
++ wkinfo->func = func;
++ wkinfo->args = args;
++ wkinfo->comp = NULL;
++ __module_get(THIS_MODULE);
++ }
++
++ AuInitWkq(&wkinfo->wk, wkq_func);
++#ifdef CONFIG_AUFS_DLGT
++ if (dlgt)
++ cred_store(&wkinfo->cred);
++#endif
++ do_wkq(wkinfo);
++ if (do_wait)
++ wait_for_completion(wkinfo->comp);
++}
++
++#if 0
++void au_wkq_wait_nwtask(void)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ wait_event(wq, !atomic_read(&au_wkq[aufs_nwkq].busy));
++}
++#endif
++
++void au_wkq_fin(void)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < aufs_nwkq; i++)
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
++ destroy_workqueue(au_wkq[i].q);
++ kfree(au_wkq);
++}
++
++int __init au_wkq_init(void)
++{
++ int err, i;
++ struct au_wkq *nowaitq;
++
++ LKTRTrace("%d\n", aufs_nwkq);
++
++ /* '+1' is for accounting of nowait queue */
++ err = -ENOMEM;
++ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
++ if (unlikely(!au_wkq))
++ goto out;
++
++ err = 0;
++ for (i = 0; i < aufs_nwkq; i++) {
++ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
++ atomic_set(&au_wkq[i].busy, 0);
++ au_wkq[i].max_busy = 0;
++ continue;
++ }
++
++ err = PTR_ERR(au_wkq[i].q);
++ au_wkq_fin();
++ break;
++ }
++
++ /* nowait accounting */
++ nowaitq = au_wkq + aufs_nwkq;
++ atomic_set(&nowaitq->busy, 0);
++ nowaitq->max_busy = 0;
++ nowaitq->q = NULL;
++
++#if 0 // test accouting
++ if (!err) {
++ static void f(void *args) {
++ DbgSleep(1);
++ }
++ int i;
++ //au_debug_on();
++ LKTRTrace("f %p\n", f);
++ for (i = 0; i < 10; i++)
++ au_wkq_nowait(f, NULL, 0);
++ for (i = 0; i < aufs_nwkq; i++)
++ au_wkq_wait(f, NULL, 0);
++ DbgSleep(11);
++ //au_debug_off();
++ }
++#endif
++
++ out:
++ TraceErr(err);
++ return err;
++}
+diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h
+new file mode 100755
+index 0000000..cc1bb25
+--- /dev/null
++++ b/fs/aufs/wkq.h
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: wkq.h,v 1.9 2007/05/14 03:39:10 sfjro Exp $ */
++
++#ifndef __AUFS_WKQ_H__
++#define __AUFS_WKQ_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sched.h>
++#include <linux/version.h>
++#include <linux/workqueue.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* internal workqueue named AUFS_WKQ_NAME */
++struct au_wkq {
++ struct workqueue_struct *q;
++
++ /* accounting */
++ atomic_t busy;
++ unsigned int max_busy;
++} ;//__attribute__ ((aligned));
++
++typedef void (*au_wkq_func_t)(void *args);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++#define AuInitWkq(wk, func) INIT_WORK(wk, func)
++#define AuWkqFunc(name, arg) void name(struct work_struct *arg)
++#else
++typedef void (*work_func_t)(void *arg);
++#define AuInitWkq(wk, func) INIT_WORK(wk, func, wk)
++#define AuWkqFunc(name, arg) void name(void *arg)
++#endif
++
++extern struct au_wkq *au_wkq;
++
++void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait);
++//void au_wkq_wait_nwtask(void);
++int __init au_wkq_init(void);
++void au_wkq_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int is_au_wkq(struct task_struct *tsk)
++{
++ return (!tsk->mm && !strcmp(current->comm, AUFS_WKQ_NAME));
++}
++
++static inline void au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
++{
++ au_wkq_run(func, args, dlgt, /*do_wait*/1);
++}
++
++static inline void au_wkq_nowait(au_wkq_func_t func, void *args, int dlgt)
++{
++ au_wkq_run(func, args, dlgt, /*do_wait*/0);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WKQ_H__ */
+diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c
+new file mode 100755
+index 0000000..145491e
+--- /dev/null
++++ b/fs/aufs/xino.c
+@@ -0,0 +1,644 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: xino.c,v 1.27 2007/05/14 03:39:10 sfjro Exp $ */
++
++//#include <linux/fs.h>
++#include <linux/fsnotify.h>
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++static readf_t find_readf(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->read)
++ return fop->read;
++ if (fop->aio_read)
++ return do_sync_read;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++static writef_t find_writef(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->write)
++ return fop->write;
++ if (fop->aio_write)
++ return do_sync_write;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t xino_fread(readf_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)size, *pos);
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ err = func(file, (char __user*)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++
++#if 0
++ if (err > 0)
++ fsnotify_access(file->f_dentry);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t do_xino_fwrite(writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ lockdep_off();
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ err = func(file, (const char __user*)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++ lockdep_on();
++
++#if 0
++ if (err > 0)
++ fsnotify_modify(file->f_dentry);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++struct do_xino_fwrite_args {
++ ssize_t *errp;
++ writef_t func;
++ struct file *file;
++ void *buf;
++ size_t size;
++ loff_t *pos;
++};
++
++static void call_do_xino_fwrite(void *args)
++{
++ struct do_xino_fwrite_args *a = args;
++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
++}
++
++static ssize_t xino_fwrite(writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)size, *pos);
++
++ // signal block and no wkq?
++ /*
++ * it breaks RLIMIT_FSIZE and normal user's limit,
++ * users should care about quota and real 'filesystem full.'
++ */
++ if (!is_au_wkq(current)) {
++ struct do_xino_fwrite_args args = {
++ .errp = &err,
++ .func = func,
++ .file = file,
++ .buf = buf,
++ .size = size,
++ .pos = pos
++ };
++ au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
++ } else
++ err = do_xino_fwrite(func, file, buf, size, pos);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * write @ino to the xinofile for the specified branch{@sb, @bindex}
++ * at the position of @_ino.
++ * when @ino is zero, it is written to the xinofile and means no entry.
++ */
++int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino)
++{
++ struct aufs_branch *br;
++ loff_t pos;
++ ssize_t sz;
++
++ LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, xino->ino);
++ //DEBUG_ON(!xino->ino /* || !xino->h_gen */);
++ //WARN_ON(bindex == 0 && h_ino == 31);
++
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ return 0;
++
++ br = stobr(sb, bindex);
++ DEBUG_ON(!br || !br->br_xino);
++ pos = h_ino * sizeof(*xino);
++ sz = xino_fwrite(br->br_xino_write, br->br_xino, xino, sizeof(*xino),
++ &pos);
++ //if (LktrCond) sz = 1;
++ if (sz == sizeof(*xino))
++ return 0; /* success */
++
++ IOErr("write failed (%ld)\n", (long)sz);
++ return -EIO;
++}
++
++int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino)
++{
++ struct xino xino = {
++ .ino = 0
++ };
++ return xino_write(sb, bindex, h_ino, &xino);
++}
++
++// why is not atomic_long_inc_return defined?
++static DEFINE_SPINLOCK(alir_lock);
++static long atomic_long_inc_return(atomic_long_t *a)
++{
++ long l;
++
++ spin_lock(&alir_lock);
++ atomic_long_inc(a);
++ l = atomic_long_read(a);
++ spin_unlock(&alir_lock);
++ return l;
++}
++
++ino_t xino_new_ino(struct super_block *sb)
++{
++ ino_t ino;
++
++ TraceEnter();
++ ino = atomic_long_inc_return(&stosi(sb)->si_xino);
++ BUILD_BUG_ON(AUFS_FIRST_INO < AUFS_ROOT_INO);
++ if (ino >= AUFS_ROOT_INO)
++ return ino;
++ else {
++ atomic_long_dec(&stosi(sb)->si_xino);
++ IOErr1("inode number overflow\n");
++ return 0;
++ }
++}
++
++/*
++ * read @ino from xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * if @ino does not exist and @do_new is true, get new one.
++ */
++int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino)
++{
++ int err;
++ struct aufs_branch *br;
++ struct file *file;
++ loff_t pos;
++ ssize_t sz;
++
++ LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
++
++ err = 0;
++ xino->ino = 0;
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ return 0; /* no ino */
++
++ br = stobr(sb, bindex);
++ file = br->br_xino;
++ DEBUG_ON(!file);
++ pos = h_ino * sizeof(*xino);
++ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xino))
++ return 0; /* no ino */
++
++ sz = xino_fread(br->br_xino_read, file, xino, sizeof(*xino), &pos);
++ if (sz == sizeof(*xino))
++ return 0; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ IOErr("xino read error (%ld)\n", (long)sz);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct file *xino_create(struct super_block *sb, char *fname, int silent,
++ struct dentry *parent)
++{
++ struct file *file;
++ int err;
++ struct dentry *hidden_parent;
++ struct inode *hidden_dir;
++ //const int udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++
++ LKTRTrace("%s\n", fname);
++ //DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++
++ // LSM may detect it
++ // use sio?
++ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ S_IRUGO | S_IWUGO);
++ //file = ERR_PTR(-1);
++ if (IS_ERR(file)) {
++ if (!silent)
++ Err("open %s(%ld)\n", fname, PTR_ERR(file));
++ return file;
++ }
++#if 0
++ if (unlikely(udba && parent))
++ au_direval_dec(parent);
++#endif
++
++ /* keep file count */
++ hidden_parent = dget_parent(file->f_dentry);
++ hidden_dir = hidden_parent->d_inode;
++ hi_lock_parent(hidden_dir);
++ err = vfsub_unlink(hidden_dir, file->f_dentry, /*dlgt*/0);
++#if 0
++ if (unlikely(!err && udba && parent))
++ au_direval_dec(parent);
++#endif
++ i_unlock(hidden_dir);
++ dput(hidden_parent);
++ if (unlikely(err)) {
++ if (!silent)
++ Err("unlink %s(%d)\n", fname, err);
++ goto out;
++ }
++ if (sb != file->f_dentry->d_sb)
++ return file; /* success */
++
++ if (!silent)
++ Err("%s must be outside\n", fname);
++ err = -EINVAL;
++
++ out:
++ fput(file);
++ file = ERR_PTR(err);
++ return file;
++}
++
++/*
++ * find another branch who is on the same filesystem of the specified
++ * branch{@btgt}. search until @bend.
++ */
++static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
++ aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++ struct super_block *tgt_sb = sbr_sb(sb, btgt);
++
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(btgt != bindex && tgt_sb == sbr_sb(sb, bindex)))
++ return bindex;
++ return -1;
++}
++
++/*
++ * create a new xinofile at the same place/path as @base_file.
++ */
++static struct file *xino_create2(struct file *base_file)
++{
++ struct file *file;
++ int err;
++ struct dentry *base, *dentry, *parent;
++ struct inode *dir;
++ struct qstr *name;
++ struct lkup_args lkup = {
++ .nfsmnt = NULL,
++ .dlgt = 0
++ };
++
++ base = base_file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(base));
++ parent = dget_parent(base);
++ dir = parent->d_inode;
++ IMustLock(dir);
++
++ file = ERR_PTR(-EINVAL);
++ if (unlikely(au_is_nfs(parent->d_sb)))
++ goto out;
++
++ // do not superio, nor NFS.
++ name = &base->d_name;
++ dentry = lkup_one(name->name, parent, name->len, &lkup);
++ //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
++ if (IS_ERR(dentry)) {
++ file = (void*)dentry;
++ Err("%.*s lookup err %ld\n", LNPair(name), PTR_ERR(dentry));
++ goto out;
++ }
++ err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, /*dlgt*/0);
++ //if (LktrCond) {vfs_unlink(dir, dentry); err = -1;}
++ if (unlikely(err)) {
++ file = ERR_PTR(err);
++ Err("%.*s create err %d\n", LNPair(name), err);
++ goto out_dput;
++ }
++ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ if (IS_ERR(file)) {
++ Err("%.*s open err %ld\n", LNPair(name), PTR_ERR(file));
++ goto out_dput;
++ }
++ err = vfsub_unlink(dir, dentry, /*dlgt*/0);
++ //if (LktrCond) err = -1;
++ if (!err)
++ goto out_dput; /* success */
++
++ Err("%.*s unlink err %d\n", LNPair(name), err);
++ fput(file);
++ file = ERR_PTR(err);
++
++ out_dput:
++ dput(dentry);
++ out:
++ dput(parent);
++ TraceErrPtr(file);
++ return file;
++}
++
++/*
++ * initialize the xinofile for the specified branch{@sb, @bindex}
++ * at the place/path where @base_file indicates.
++ * test whether another branch is on the same filesystem or not,
++ * if @do_test is true.
++ */
++int xino_init(struct super_block *sb, aufs_bindex_t bindex,
++ struct file *base_file, int do_test)
++{
++ int err;
++ struct aufs_branch *br;
++ aufs_bindex_t bshared, bend;
++ struct file *file;
++ struct inode *inode, *hidden_inode;
++ struct xino xino;
++
++ LKTRTrace("b%d, base_file %p, do_test %d\n",
++ bindex, base_file, do_test);
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++ br = stobr(sb, bindex);
++ DEBUG_ON(br->br_xino);
++
++ file = NULL;
++ bshared = -1;
++ bend = sbend(sb);
++ if (do_test)
++ bshared = is_sb_shared(sb, bindex, bend);
++ if (unlikely(bshared >= 0)) {
++ struct aufs_branch *shared_br = stobr(sb, bshared);
++ if (shared_br->br_xino) {
++ file = shared_br->br_xino;
++ get_file(file);
++ }
++ }
++
++ if (!file) {
++ struct dentry *parent = dget_parent(base_file->f_dentry);
++ struct inode *dir = parent->d_inode;
++
++ hi_lock_parent(dir);
++ file = xino_create2(base_file);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ i_unlock(dir);
++ dput(parent);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ }
++ br->br_xino_read = find_readf(file);
++ err = PTR_ERR(br->br_xino_read);
++ if (IS_ERR(br->br_xino_read))
++ goto out_put;
++ br->br_xino_write = find_writef(file);
++ err = PTR_ERR(br->br_xino_write);
++ if (IS_ERR(br->br_xino_write))
++ goto out_put;
++ br->br_xino = file;
++
++ inode = sb->s_root->d_inode;
++ hidden_inode = au_h_iptr_i(inode, bindex);
++ xino.ino = inode->i_ino;
++ //xino.h_gen = hidden_inode->i_generation;
++ //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ err = xino_write(sb, bindex, hidden_inode->i_ino, &xino);
++ //if (LktrCond) err = -1;
++ if (!err)
++ return 0; /* success */
++
++ br->br_xino = NULL;
++
++ out_put:
++ fput(file);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * set xino mount option.
++ */
++int xino_set(struct super_block *sb, struct opt_xino *xino, int remount)
++{
++ int err, sparse;
++ aufs_bindex_t bindex, bend;
++ struct aufs_branch *br;
++ struct dentry *parent;
++ struct qstr *name;
++ struct file *cur_xino;
++ struct inode *dir;
++
++ LKTRTrace("%s\n", xino->path);
++
++ err = 0;
++ name = &xino->file->f_dentry->d_name;
++ parent = dget_parent(xino->file->f_dentry);
++ dir = parent->d_inode;
++ cur_xino = stobr(sb, 0)->br_xino;
++ if (remount
++ && cur_xino
++ && cur_xino->f_dentry->d_parent == parent
++ && name->len == cur_xino->f_dentry->d_name.len
++ && !memcmp(name->name, cur_xino->f_dentry->d_name.name, name->len))
++ goto out;
++
++ au_flag_set(sb, AuFlag_XINO);
++ bend = sbend(sb);
++ for (bindex = bend; bindex >= 0; bindex--) {
++ br = stobr(sb, bindex);
++ if (unlikely(br->br_xino && file_count(br->br_xino) > 1)) {
++ fput(br->br_xino);
++ br->br_xino = NULL;
++ }
++ }
++
++ for (bindex = 0; bindex <= bend; bindex++) {
++ struct file *file;
++ struct inode *inode;
++
++ br = stobr(sb, bindex);
++ if (unlikely(!br->br_xino))
++ continue;
++
++ DEBUG_ON(file_count(br->br_xino) != 1);
++ hi_lock_parent(dir);
++ file = xino_create2(xino->file);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ err = PTR_ERR(file);
++ if (IS_ERR(file)) {
++ i_unlock(dir);
++ break;
++ }
++ inode = br->br_xino->f_dentry->d_inode;
++ err = au_copy_file(file, br->br_xino, i_size_read(inode), sb,
++ &sparse);
++ //if (LktrCond) err = -1;
++ i_unlock(dir);
++ if (unlikely(err)) {
++ fput(file);
++ break;
++ }
++ fput(br->br_xino);
++ br->br_xino = file;
++ br->br_xino_read = find_readf(file);
++ DEBUG_ON(IS_ERR(br->br_xino_read));
++ br->br_xino_write = find_writef(file);
++ DEBUG_ON(IS_ERR(br->br_xino_write));
++ }
++
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(!stobr(sb, bindex)->br_xino)) {
++ err = xino_init(sb, bindex, xino->file, /*do_test*/1);
++ //if (LktrCond) {fput(stobr(sb, bindex)->br_xino);
++ //stobr(sb, bindex)->br_xino = NULL; err = -1;}
++ if (!err)
++ continue;
++ IOErr("creating xino for branch %d(%d), "
++ "forcing noxino\n", bindex, err);
++ err = -EIO;
++ break;
++ }
++ out:
++ dput(parent);
++ if (!err)
++ au_flag_set(sb, AuFlag_XINO);
++ else
++ au_flag_clr(sb, AuFlag_XINO);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * clear xino mount option
++ */
++int xino_clr(struct super_block *sb)
++{
++ aufs_bindex_t bindex, bend;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ struct aufs_branch *br;
++ br = stobr(sb, bindex);
++ if (br->br_xino) {
++ fput(br->br_xino);
++ br->br_xino = NULL;
++ }
++ }
++
++ //todo: need to make iunique() to return the larger inode number
++
++ au_flag_clr(sb, AuFlag_XINO);
++ return 0;
++}
++
++/*
++ * create a xinofile at the default place/path.
++ */
++struct file *xino_def(struct super_block *sb)
++{
++ struct file *file;
++ aufs_bindex_t bend, bindex, bwr;
++ char *page, *p;
++
++ bend = sbend(sb);
++ bwr = -1;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (br_writable(sbr_perm(sb, bindex))
++ && !au_is_nfs(au_h_dptr_i(sb->s_root, bindex)->d_sb)) {
++ bwr = bindex;
++ break;
++ }
++
++ if (bwr != -1) {
++ // todo: rewrite with lkup_one()
++ file = ERR_PTR(-ENOMEM);
++ page = __getname();
++ //if (LktrCond) {__putname(page); page = NULL;}
++ if (unlikely(!page))
++ goto out;
++ p = d_path(au_h_dptr_i(sb->s_root, bwr), sbr_mnt(sb, bwr), page,
++ PATH_MAX - sizeof(AUFS_XINO_FNAME));
++ //if (LktrCond) p = ERR_PTR(-1);
++ file = (void*)p;
++ if (p && !IS_ERR(p)) {
++ strcat(p, "/" AUFS_XINO_FNAME);
++ LKTRTrace("%s\n", p);
++ file = xino_create(sb, p, /*silent*/0, sb->s_root);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ }
++ __putname(page);
++ } else {
++ file = xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
++ /*parent*/NULL);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ }
++
++ out:
++ TraceErrPtr(file);
++ return file;
++}
+diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
+new file mode 100644
+index 0000000..1bc7b06
+--- /dev/null
++++ b/fs/squashfs/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++obj-$(CONFIG_SQUASHFS) += squashfs.o
++squashfs-y += inode.o
++squashfs-y += squashfs2_0.o
+diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
+new file mode 100644
+index 0000000..895b699
+--- /dev/null
++++ b/fs/squashfs/inode.c
+@@ -0,0 +1,2329 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/zlib.h>
++#include <linux/fs.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/vmalloc.h>
++#include <linux/smp_lock.h>
++
++#include "squashfs.h"
++
++static void vfs_read_inode(struct inode *i);
++static struct dentry *squashfs_get_parent(struct dentry *child);
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
++static int squashfs_statfs(struct dentry *, struct kstatfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
++ struct nameidata *);
++static int squashfs_remount(struct super_block *s, int *flags, char *data);
++static void squashfs_put_super(struct super_block *);
++static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
++ struct vfsmount *);
++static struct inode *squashfs_alloc_inode(struct super_block *sb);
++static void squashfs_destroy_inode(struct inode *inode);
++static int init_inodecache(void);
++static void destroy_inodecache(void);
++
++static struct file_system_type squashfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "squashfs",
++ .get_sb = squashfs_get_sb,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV
++};
++
++static const unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_super_ops = {
++ .alloc_inode = squashfs_alloc_inode,
++ .destroy_inode = squashfs_destroy_inode,
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++ .remount_fs = squashfs_remount
++};
++
++static struct super_operations squashfs_export_super_ops = {
++ .alloc_inode = squashfs_alloc_inode,
++ .destroy_inode = squashfs_destroy_inode,
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++ .read_inode = vfs_read_inode
++};
++
++static struct export_operations squashfs_export_ops = {
++ .get_parent = squashfs_get_parent
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
++ .readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_aops = {
++ .readpage = squashfs_readpage
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
++ .readpage = squashfs_readpage4K
++};
++
++static const struct file_operations squashfs_dir_ops = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir
++};
++
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
++ .lookup = squashfs_lookup
++};
++
++
++static struct buffer_head *get_block_length(struct super_block *s,
++ int *cur_index, int *offset, int *c_byte)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned short temp;
++ struct buffer_head *bh;
++
++ if (!(bh = sb_bread(s, *cur_index)))
++ goto out;
++
++ if (msblk->devblksize - *offset == 1) {
++ if (msblk->swap)
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ else
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ if (msblk->swap)
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ bh->b_data);
++ else
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ bh->b_data);
++ *c_byte = temp;
++ *offset = 1;
++ } else {
++ if (msblk->swap) {
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ } else {
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ }
++ *c_byte = temp;
++ *offset += 2;
++ }
++
++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++ if (*offset == msblk->devblksize) {
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ *offset = 0;
++ }
++ if (*((unsigned char *) (bh->b_data + *offset)) !=
++ SQUASHFS_MARKER_BYTE) {
++ ERROR("Metadata block marker corrupt @ %x\n",
++ *cur_index);
++ brelse(bh);
++ goto out;
++ }
++ (*offset)++;
++ }
++ return bh;
++
++out:
++ return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index, int srclength)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++ msblk->devblksize_log2) + 2];
++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++ unsigned int cur_index = index >> msblk->devblksize_log2;
++ int bytes, avail_bytes, b = 0, k = 0;
++ unsigned int compressed;
++ unsigned int c_byte = length;
++
++ if (c_byte) {
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte, srclength);
++
++ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
++
++ if (!(bh[0] = sb_getblk(s, cur_index)))
++ goto block_release;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b, bh);
++ } else {
++ if (index < 0 || (index + 2) > sblk->bytes_used)
++ goto read_failure;
++
++ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++ &c_byte)))
++ goto read_failure;
++
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED(c_byte);
++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b - 1, bh + 1);
++ }
++
++ if (compressed) {
++ int zlib_err = 0;
++
++ /*
++ * uncompress block
++ */
++
++ mutex_lock(&msblk->read_data_mutex);
++
++ msblk->stream.next_out = buffer;
++ msblk->stream.avail_out = srclength;
++
++ for (bytes = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto release_mutex;
++
++ msblk->stream.next_in = bh[k]->b_data + offset;
++ msblk->stream.avail_in = avail_bytes;
++
++ if (k == 0) {
++ zlib_err = zlib_inflateInit(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateInit returned unexpected result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++
++ if (avail_bytes == 0) {
++ offset = 0;
++ brelse(bh[k]);
++ continue;
++ }
++ }
++
++ zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
++ if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
++ ERROR("zlib_inflate returned unexpected result 0x%x, srclength %d, avail_in %d, avail_out %d\n",
++ zlib_err, srclength, msblk->stream.avail_in, msblk->stream.avail_out);
++ goto release_mutex;
++ }
++
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++
++ if (zlib_err != Z_STREAM_END)
++ goto release_mutex;
++
++ zlib_err = zlib_inflateEnd(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateEnd returned unexpected result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++ bytes = msblk->stream.total_out;
++ mutex_unlock(&msblk->read_data_mutex);
++ } else {
++ int i;
++
++ for(i = 0; i < b; i++) {
++ wait_on_buffer(bh[i]);
++ if(!buffer_uptodate(bh[i]))
++ goto block_release;
++ }
++
++ for (bytes = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++ }
++
++ if (next_index)
++ *next_index = index + c_byte + (length ? 0 :
++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++ ? 3 : 2));
++ return bytes;
++
++release_mutex:
++ mutex_unlock(&msblk->read_data_mutex);
++
++block_release:
++ for (; k < b; k++)
++ brelse(bh[k]);
++
++read_failure:
++ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++ return 0;
++}
++
++
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ int n, i, bytes, return_length = length;
++ long long next_index;
++
++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++ while ( 1 ) {
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (msblk->block_cache[i].block == block)
++ break;
++
++ mutex_lock(&msblk->block_cache_mutex);
++
++ if (i == SQUASHFS_CACHED_BLKS) {
++ /* read inode header block */
++ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++ n ; n --, i = (i + 1) %
++ SQUASHFS_CACHED_BLKS)
++ if (msblk->block_cache[i].block !=
++ SQUASHFS_USED_BLK)
++ break;
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->waitq, &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ mutex_unlock(&msblk->block_cache_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->waitq, &wait);
++ continue;
++ }
++ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++ if (msblk->block_cache[i].block ==
++ SQUASHFS_INVALID_BLK) {
++ if (!(msblk->block_cache[i].data =
++ kmalloc(SQUASHFS_METADATA_SIZE,
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate cache"
++ "block\n");
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ }
++ }
++
++ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++ mutex_unlock(&msblk->block_cache_mutex);
++
++ msblk->block_cache[i].length = squashfs_read_data(s,
++ msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
++ if (msblk->block_cache[i].length == 0) {
++ ERROR("Unable to read cache block [%llx:%x]\n",
++ block, offset);
++ mutex_lock(&msblk->block_cache_mutex);
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++ kfree(msblk->block_cache[i].data);
++ wake_up(&msblk->waitq);
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ }
++
++ mutex_lock(&msblk->block_cache_mutex);
++ wake_up(&msblk->waitq);
++ msblk->block_cache[i].block = block;
++ msblk->block_cache[i].next_index = next_index;
++ TRACE("Read cache block [%llx:%x]\n", block, offset);
++ }
++
++ if (msblk->block_cache[i].block != block) {
++ mutex_unlock(&msblk->block_cache_mutex);
++ continue;
++ }
++
++ bytes = msblk->block_cache[i].length - offset;
++
++ if (bytes < 1) {
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ } else if (bytes >= length) {
++ if (buffer)
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, length);
++ if (msblk->block_cache[i].length - offset == length) {
++ *next_block = msblk->block_cache[i].next_index;
++ *next_offset = 0;
++ } else {
++ *next_block = block;
++ *next_offset = offset + length;
++ }
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto finish;
++ } else {
++ if (buffer) {
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, bytes);
++ buffer += bytes;
++ }
++ block = msblk->block_cache[i].next_index;
++ mutex_unlock(&msblk->block_cache_mutex);
++ length -= bytes;
++ offset = 0;
++ }
++ }
++
++finish:
++ return return_length;
++out:
++ return 0;
++}
++
++
++static int get_fragment_location(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++ struct squashfs_fragment_entry fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment)
++{
++ mutex_lock(&msblk->fragment_mutex);
++ fragment->locked --;
++ wake_up(&msblk->fragment_wait_queue);
++ mutex_unlock(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length)
++{
++ int i, n;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ while ( 1 ) {
++ mutex_lock(&msblk->fragment_mutex);
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++ msblk->fragment[i].block != start_block; i++);
++
++ if (i == SQUASHFS_CACHED_FRAGMENTS) {
++ for (i = msblk->next_fragment, n =
++ SQUASHFS_CACHED_FRAGMENTS; n &&
++ msblk->fragment[i].locked; n--, i = (i + 1) %
++ SQUASHFS_CACHED_FRAGMENTS);
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ mutex_unlock(&msblk->fragment_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ continue;
++ }
++ msblk->next_fragment = (msblk->next_fragment + 1) %
++ SQUASHFS_CACHED_FRAGMENTS;
++
++ if (msblk->fragment[i].data == NULL)
++ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++ (SQUASHFS_FILE_MAX_SIZE))) {
++ ERROR("Failed to allocate fragment "
++ "cache block\n");
++ mutex_unlock(&msblk->fragment_mutex);
++ goto out;
++ }
++
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].locked = 1;
++ mutex_unlock(&msblk->fragment_mutex);
++
++ if (!(msblk->fragment[i].length = squashfs_read_data(s,
++ msblk->fragment[i].data,
++ start_block, length, NULL, sblk->block_size))) {
++ ERROR("Unable to read fragment cache block "
++ "[%llx]\n", start_block);
++ msblk->fragment[i].locked = 0;
++ smp_mb();
++ goto out;
++ }
++
++ mutex_lock(&msblk->fragment_mutex);
++ msblk->fragment[i].block = start_block;
++ TRACE("New fragment %d, start block %lld, locked %d\n",
++ i, msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ mutex_unlock(&msblk->fragment_mutex);
++ break;
++ }
++
++ msblk->fragment[i].locked++;
++ mutex_unlock(&msblk->fragment_mutex);
++ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++ msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ return &msblk->fragment[i];
++
++out:
++ return NULL;
++}
++
++
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
++ struct squashfs_base_inode_header *inodeb)
++{
++ i->i_ino = inodeb->inode_number;
++ i->i_mtime.tv_sec = inodeb->mtime;
++ i->i_atime.tv_sec = inodeb->mtime;
++ i->i_ctime.tv_sec = inodeb->mtime;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++}
++
++
++static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
++ int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
++ squashfs_inode_t inode;
++
++ TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
++
++ if (msblk->swap) {
++ squashfs_inode_t sinode;
++
++ if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
++ sizeof(sinode), &start, &offset))
++ goto out;
++ SQUASHFS_SWAP_INODE_T((&inode), &sinode);
++ } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
++ sizeof(inode), &start, &offset))
++ goto out;
++
++ TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
++
++ return inode;
++
++out:
++ return SQUASHFS_INVALID_BLK;
++}
++
++
++static void vfs_read_inode(struct inode *i)
++{
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
++
++ TRACE("Entered vfs_read_inode\n");
++
++ if(inode != SQUASHFS_INVALID_BLK)
++ (msblk->read_inode)(i, inode);
++}
++
++
++static struct dentry *squashfs_get_parent(struct dentry *child)
++{
++ struct inode *i = child->d_inode;
++ struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
++ struct dentry *rv;
++
++ TRACE("Entered squashfs_get_parent\n");
++
++ if(parent == NULL) {
++ rv = ERR_PTR(-EACCES);
++ goto out;
++ }
++
++ rv = d_alloc_anon(parent);
++ if(rv == NULL)
++ rv = ERR_PTR(-ENOMEM);
++
++out:
++ return rv;
++}
++
++
++SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct inode *i = iget_locked(s, inode_number);
++
++ TRACE("Entered squashfs_iget\n");
++
++ if(i && (i->i_state & I_NEW)) {
++ (msblk->read_inode)(i, inode);
++ unlock_new_inode(i);
++ }
++
++ return i;
++}
++
++
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
++{
++ struct super_block *s = i->i_sb;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header id, sid;
++ struct squashfs_base_inode_header *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_read_inode\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ squashfs_new_inode(msblk, i, inodeb);
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_reg_inode_header *inodep = &id.reg;
++ struct squashfs_reg_inode_header *sinodep = &sid.reg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_nlink = 1;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_LREG_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_lreg_inode_header *inodep = &id.lreg;
++ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header *inodep = &id.dir;
++ struct squashfs_dir_inode_header *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header *inodep = &id.dev;
++ struct squashfs_dev_inode_header *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ struct squashfs_ipc_inode_header *inodep = &id.ipc;
++ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ return 1;
++
++failed_read:
++ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
++
++failed_read1:
++ make_bad_inode(i);
++ return 0;
++}
++
++
++static int read_inode_lookup_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
++
++ TRACE("In read_inode_lookup_table, length %d\n", length);
++
++ /* Allocate inode lookup table */
++ if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
++ ERROR("Failed to allocate inode lookup table\n");
++ return 0;
++ }
++
++ if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
++ sblk->lookup_table_start, length |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
++ ERROR("unable to read inode lookup table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long block;
++
++ for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
++ SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
++ &msblk->inode_lookup_table[i], 1);
++ msblk->inode_lookup_table[i] = block;
++ }
++ }
++
++ return 1;
++}
++
++
++static int read_fragment_index_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
++
++ if(length == 0)
++ return 1;
++
++ /* Allocate fragment index table */
++ if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment index table\n");
++ return 0;
++ }
++
++ if (!squashfs_read_data(s, (char *) msblk->fragment_index,
++ sblk->fragment_table_start, length |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++ &msblk->fragment_index[i], 1);
++ msblk->fragment_index[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->read_inode = squashfs_read_inode;
++ msblk->read_blocklist = read_blocklist;
++ msblk->read_fragment_index_table = read_fragment_index_table;
++
++ if (sblk->s_major == 1) {
++ if (!squashfs_1_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 1.0 support enabled\n");
++ return 0;
++ }
++ } else if (sblk->s_major == 2) {
++ if (!squashfs_2_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 2.0 support enabled\n");
++ return 0;
++ }
++ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++ SQUASHFS_MINOR) {
++ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++ "filesystem\n", sblk->s_major, sblk->s_minor);
++ SERROR("Please update your kernel\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)
++{
++ struct squashfs_sb_info *msblk;
++ struct squashfs_super_block *sblk;
++ int i;
++ char b[BDEVNAME_SIZE];
++ struct inode *root;
++
++ TRACE("Entered squashfs_read_superblock\n");
++
++ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate superblock\n");
++ goto failure;
++ }
++ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
++ msblk = s->s_fs_info;
++ if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++ ERROR("Failed to allocate zlib workspace\n");
++ goto failure;
++ }
++ sblk = &msblk->sblk;
++
++ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
++ msblk->devblksize_log2 = ffz(~msblk->devblksize);
++
++ mutex_init(&msblk->read_data_mutex);
++ mutex_init(&msblk->read_page_mutex);
++ mutex_init(&msblk->block_cache_mutex);
++ mutex_init(&msblk->fragment_mutex);
++ mutex_init(&msblk->meta_index_mutex);
++
++ init_waitqueue_head(&msblk->waitq);
++ init_waitqueue_head(&msblk->fragment_wait_queue);
++
++ sblk->bytes_used = sizeof(struct squashfs_super_block);
++ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++ sizeof(struct squashfs_super_block) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
++ SERROR("unable to read superblock\n");
++ goto failed_mount;
++ }
++
++ /* Check it is a SQUASHFS superblock */
++ msblk->swap = 0;
++ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++ struct squashfs_super_block ssblk;
++
++ WARNING("Mounting a different endian SQUASHFS "
++ "filesystem on %s\n", bdevname(s->s_bdev, b));
++
++ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++ msblk->swap = 1;
++ } else {
++ SERROR("Can't find a SQUASHFS superblock on %s\n",
++ bdevname(s->s_bdev, b));
++ goto failed_mount;
++ }
++ }
++
++ /* Check the MAJOR & MINOR versions */
++ if(!supported_squashfs_filesystem(msblk, silent))
++ goto failed_mount;
++
++ /* Check the filesystem does not extend beyond the end of the
++ block device */
++ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
++ goto failed_mount;
++
++ /* Check the root inode for sanity */
++ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
++ goto failed_mount;
++
++ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
++ TRACE("Inodes are %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_INODES
++ (sblk->flags) ? "un" : "");
++ TRACE("Data is %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++ ? "un" : "");
++ TRACE("Check data is %s present in the filesystem\n",
++ SQUASHFS_CHECK_DATA(sblk->flags) ?
++ "" : "not");
++ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++ TRACE("Block size %d\n", sblk->block_size);
++ TRACE("Number of inodes %d\n", sblk->inodes);
++ if (sblk->s_major > 1)
++ TRACE("Number of fragments %d\n", sblk->fragments);
++ TRACE("Number of uids %d\n", sblk->no_uids);
++ TRACE("Number of gids %d\n", sblk->no_guids);
++ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++ if (sblk->s_major > 1)
++ TRACE("sblk->fragment_table_start %llx\n",
++ sblk->fragment_table_start);
++ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++ s->s_flags |= MS_RDONLY;
++ s->s_op = &squashfs_super_ops;
++
++ /* Init inode_table block pointer array */
++ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++ ERROR("Failed to allocate block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++ msblk->next_cache = 0;
++
++ /* Allocate read_page block */
++ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_page block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate uid and gid tables */
++ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ goto failed_mount;
++ }
++ msblk->guid = msblk->uid + sblk->no_uids;
++
++ if (msblk->swap) {
++ unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++ sblk->no_guids), (sizeof(unsigned int) * 8));
++ } else
++ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++
++ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++ goto allocate_root;
++
++ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++ msblk->fragment[i].locked = 0;
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].data = NULL;
++ }
++
++ msblk->next_fragment = 0;
++
++ /* Allocate and read fragment index table */
++ if (msblk->read_fragment_index_table(s) == 0)
++ goto failed_mount;
++
++ if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
++ goto allocate_root;
++
++ /* Allocate and read inode lookup table */
++ if (read_inode_lookup_table(s) == 0)
++ goto failed_mount;
++
++ s->s_op = &squashfs_export_super_ops;
++ s->s_export_op = &squashfs_export_ops;
++
++allocate_root:
++ root = new_inode(s);
++ if ((msblk->read_inode)(root, sblk->root_inode) == 0)
++ goto failed_mount;
++ insert_inode_hash(root);
++
++ if ((s->s_root = d_alloc_root(root)) == NULL) {
++ ERROR("Root inode create failed\n");
++ iput(root);
++ goto failed_mount;
++ }
++
++ TRACE("Leaving squashfs_read_super\n");
++ return 0;
++
++failed_mount:
++ kfree(msblk->inode_lookup_table);
++ kfree(msblk->fragment_index);
++ kfree(msblk->fragment);
++ kfree(msblk->uid);
++ kfree(msblk->read_page);
++ kfree(msblk->block_cache);
++ kfree(msblk->fragment_index_2);
++ vfree(msblk->stream.workspace);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ return -EINVAL;
++
++failure:
++ return -ENOMEM;
++}
++
++
++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ TRACE("Entered squashfs_statfs\n");
++
++ buf->f_type = SQUASHFS_MAGIC;
++ buf->f_bsize = sblk->block_size;
++ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++ buf->f_bfree = buf->f_bavail = 0;
++ buf->f_files = sblk->inodes;
++ buf->f_ffree = 0;
++ buf->f_namelen = SQUASHFS_NAME_LEN;
++
++ return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++ long long block = SQUASHFS_I(inode)->start_block;
++ int offset = SQUASHFS_I(inode)->offset;
++ void *pageaddr = kmap(page);
++
++ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++ "%llx, offset %x\n", page->index,
++ SQUASHFS_I(inode)->start_block,
++ SQUASHFS_I(inode)->offset);
++
++ for (length = 0; length < index; length += bytes) {
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++ block, offset, PAGE_CACHE_SIZE, &block,
++ &offset))) {
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++ offset);
++ goto skip_read;
++ }
++ }
++
++ if (length != index) {
++ ERROR("(squashfs_symlink_readpage) length != index\n");
++ bytes = 0;
++ goto skip_read;
++ }
++
++ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++ i_size_read(inode) - length;
++
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++ offset, bytes, &block, &offset)))
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap(page);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++ struct meta_index *meta = NULL;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ int i;
++
++ mutex_lock(&msblk->meta_index_mutex);
++
++ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++ if(msblk->meta_index == NULL)
++ goto not_allocated;
++
++ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++ if (msblk->meta_index[i].inode_number == inode->i_ino &&
++ msblk->meta_index[i].offset >= offset &&
++ msblk->meta_index[i].offset <= index &&
++ msblk->meta_index[i].locked == 0) {
++ TRACE("locate_meta_index: entry %d, offset %d\n", i,
++ msblk->meta_index[i].offset);
++ meta = &msblk->meta_index[i];
++ offset = meta->offset;
++ }
++
++ if (meta)
++ meta->locked = 1;
++
++not_allocated:
++ mutex_unlock(&msblk->meta_index_mutex);
++
++ return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct meta_index *meta = NULL;
++ int i;
++
++ mutex_lock(&msblk->meta_index_mutex);
++
++ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++ if(msblk->meta_index == NULL) {
++ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++ ERROR("Failed to allocate meta_index\n");
++ goto failed;
++ }
++ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++ msblk->meta_index[i].inode_number = 0;
++ msblk->meta_index[i].locked = 0;
++ }
++ msblk->next_meta_index = 0;
++ }
++
++ for(i = SQUASHFS_META_NUMBER; i &&
++ msblk->meta_index[msblk->next_meta_index].locked; i --)
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ if(i == 0) {
++ TRACE("empty_meta_index: failed!\n");
++ goto failed;
++ }
++
++ TRACE("empty_meta_index: returned meta entry %d, %p\n",
++ msblk->next_meta_index,
++ &msblk->meta_index[msblk->next_meta_index]);
++
++ meta = &msblk->meta_index[msblk->next_meta_index];
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ meta->inode_number = inode->i_ino;
++ meta->offset = offset;
++ meta->skip = skip;
++ meta->entries = 0;
++ meta->locked = 1;
++
++failed:
++ mutex_unlock(&msblk->meta_index_mutex);
++ return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++ meta->locked = 0;
++ smp_mb();
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++ long long *start_block, int *offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned int *block_listp;
++ int block = 0;
++
++ if (msblk->swap) {
++ char sblock_list[blocks << 2];
++
++ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++ ((unsigned int *)sblock_list), blocks);
++ } else
++ if (!squashfs_get_cached_block(s, block_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++
++ for (block_listp = (unsigned int *) block_list; blocks;
++ block_listp++, blocks --)
++ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++ return block;
++
++failure:
++ return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++ return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++ long long *index_block, int *index_offset,
++ long long *data_block, char *block_list)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++ int offset = 0;
++ struct meta_index *meta;
++ struct meta_entry *meta_entry;
++ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++ int cur_offset = SQUASHFS_I(inode)->offset;
++ long long cur_data_block = SQUASHFS_I(inode)->start_block;
++ int i;
++
++ index /= SQUASHFS_META_INDEXES * skip;
++
++ while ( offset < index ) {
++ meta = locate_meta_index(inode, index, offset + 1);
++
++ if (meta == NULL) {
++ if ((meta = empty_meta_index(inode, offset + 1,
++ skip)) == NULL)
++ goto all_done;
++ } else {
++ if(meta->entries == 0)
++ goto failed;
++ offset = index < meta->offset + meta->entries ? index :
++ meta->offset + meta->entries - 1;
++ meta_entry = &meta->meta_entry[offset - meta->offset];
++ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++ cur_offset = meta_entry->offset;
++ cur_data_block = meta_entry->data_block;
++ TRACE("get_meta_index: offset %d, meta->offset %d, "
++ "meta->entries %d\n", offset, meta->offset,
++ meta->entries);
++ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++ " data_block 0x%llx\n", cur_index_block,
++ cur_offset, cur_data_block);
++ }
++
++ for (i = meta->offset + meta->entries; i <= index &&
++ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++ int blocks = skip * SQUASHFS_META_INDEXES;
++
++ while (blocks) {
++ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++ blocks;
++ int res = read_block_index(inode->i_sb, block,
++ block_list, &cur_index_block,
++ &cur_offset);
++
++ if (res == -1)
++ goto failed;
++
++ cur_data_block += res;
++ blocks -= block;
++ }
++
++ meta_entry = &meta->meta_entry[i - meta->offset];
++ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++ meta_entry->offset = cur_offset;
++ meta_entry->data_block = cur_data_block;
++ meta->entries ++;
++ offset ++;
++ }
++
++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++ meta->offset, meta->entries);
++
++ release_meta_index(inode, meta);
++ }
++
++all_done:
++ *index_block = cur_index_block;
++ *index_offset = cur_offset;
++ *data_block = cur_data_block;
++
++ return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++ release_meta_index(inode, meta);
++ return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize)
++{
++ long long block_ptr;
++ int offset;
++ long long block;
++ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++ block_list);
++
++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++ block);
++
++ if(res == -1)
++ goto failure;
++
++ index -= res;
++
++ while ( index ) {
++ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++ int res = read_block_index(inode->i_sb, blocks, block_list,
++ &block_ptr, &offset);
++ if (res == -1)
++ goto failure;
++ block += res;
++ index -= blocks;
++ }
++
++ if (read_block_index(inode->i_sb, 1, block_list,
++ &block_ptr, &offset) == -1)
++ goto failure;
++ *bsize = *((unsigned int *) block_list);
++
++ return block;
++
++failure:
++ return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char *block_list;
++ long long block;
++ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++ void *pageaddr;
++ struct squashfs_fragment_cache *fragment = NULL;
++ char *data_ptr = msblk->read_page;
++
++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++ int start_index = page->index & ~mask;
++ int end_index = start_index | mask;
++
++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
++ ERROR("Failed to allocate block_list\n");
++ goto skip_read;
++ }
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT))
++ goto skip_read;
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ if ((block = (msblk->read_blocklist)(inode, index, 1,
++ block_list, NULL, &bsize)) == 0)
++ goto skip_read;
++
++ mutex_lock(&msblk->read_page_mutex);
++
++ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++ block, bsize, NULL, sblk->block_size))) {
++ ERROR("Unable to read page, block %llx, size %x\n", block,
++ bsize);
++ mutex_unlock(&msblk->read_page_mutex);
++ goto skip_read;
++ }
++ } else {
++ if ((fragment = get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)->u.s1.fragment_size))
++ == NULL) {
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ (int) SQUASHFS_I(inode)->
++ u.s1.fragment_size);
++ goto skip_read;
++ }
++ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++ (i_size_read(inode) & (sblk->block_size
++ - 1));
++ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++ data_ptr = fragment->data;
++ }
++
++ for (i = start_index; i <= end_index && byte_offset < bytes;
++ i++, byte_offset += PAGE_CACHE_SIZE) {
++ struct page *push_page;
++ int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++ PAGE_CACHE_SIZE : bytes - byte_offset;
++
++ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++ bytes, i, byte_offset, avail);
++
++ push_page = (i == page->index) ? page :
++ grab_cache_page_nowait(page->mapping, i);
++
++ if (!push_page)
++ continue;
++
++ if (PageUptodate(push_page))
++ goto skip_page;
++
++ pageaddr = kmap_atomic(push_page, KM_USER0);
++ memcpy(pageaddr, data_ptr + byte_offset, avail);
++ memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(push_page);
++ SetPageUptodate(push_page);
++skip_page:
++ unlock_page(push_page);
++ if(i != page->index)
++ page_cache_release(push_page);
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log))
++ mutex_unlock(&msblk->read_page_mutex);
++ else
++ release_cached_fragment(msblk, fragment);
++
++ kfree(block_list);
++ return 0;
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ kfree(block_list);
++ return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char *block_list;
++ long long block;
++ unsigned int bsize, bytes = 0;
++ void *pageaddr;
++
++ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT)) {
++ block_list = NULL;
++ goto skip_read;
++ }
++
++ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
++ ERROR("Failed to allocate block_list\n");
++ goto skip_read;
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || page->index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ block = (msblk->read_blocklist)(inode, page->index, 1,
++ block_list, NULL, &bsize);
++ if(block == 0)
++ goto skip_read;
++
++ mutex_lock(&msblk->read_page_mutex);
++ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++ bsize, NULL, sblk->block_size);
++ if (bytes) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, msblk->read_page, bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ block, bsize);
++ mutex_unlock(&msblk->read_page_mutex);
++ } else {
++ struct squashfs_fragment_cache *fragment =
++ get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ if (fragment) {
++ bytes = i_size_read(inode) & (sblk->block_size - 1);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++ u.s1.fragment_offset, bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ release_cached_fragment(msblk, fragment);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block, (int)
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ }
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ kfree(block_list);
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ f_pos =- 3;
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length + 3;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index *index;
++ char *str;
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_index\n");
++ goto failure;
++ }
++
++ index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ kfree(str);
++failure:
++ return length + 3;
++}
++
++
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ struct squashfs_dir_entry *dire;
++
++ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto finish;
++ }
++
++ while(file->f_pos < 3) {
++ char *name;
++ int size, i_ino;
++
++ if(file->f_pos == 0) {
++ name = ".";
++ size = 1;
++ i_ino = i->i_ino;
++ } else {
++ name = "..";
++ size = 2;
++ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++ }
++ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++ (unsigned int) dirent, name, size, (int)
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]);
++
++ if (filldir(dirent, name, size,
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]) < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos += size;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ }
++ }
++
++finish:
++ kfree(dire);
++ return 0;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ kfree(dire);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ struct squashfs_dir_entry *dire;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto exit_lookup;
++ }
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_lookup;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (name[0] < dire->name[0])
++ goto exit_lookup;
++
++ if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
++ squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %d\n", name,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number);
++
++ inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
++
++ goto exit_lookup;
++ }
++ }
++ }
++
++exit_lookup:
++ kfree(dire);
++ if (inode)
++ return d_splice_alias(inode, dentry);
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_lookup;
++}
++
++
++static int squashfs_remount(struct super_block *s, int *flags, char *data)
++{
++ *flags |= MS_RDONLY;
++ return 0;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++ int i;
++
++ if (s->s_fs_info) {
++ struct squashfs_sb_info *sbi = s->s_fs_info;
++ if (sbi->block_cache)
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (sbi->block_cache[i].block !=
++ SQUASHFS_INVALID_BLK)
++ kfree(sbi->block_cache[i].data);
++ if (sbi->fragment)
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
++ SQUASHFS_FREE(sbi->fragment[i].data);
++ kfree(sbi->fragment);
++ kfree(sbi->block_cache);
++ kfree(sbi->read_page);
++ kfree(sbi->uid);
++ kfree(sbi->fragment_index);
++ kfree(sbi->fragment_index_2);
++ kfree(sbi->meta_index);
++ vfree(sbi->stream.workspace);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ }
++}
++
++
++static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data,
++ struct vfsmount *mnt)
++{
++ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
++ mnt);
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++ int err = init_inodecache();
++ if (err)
++ goto out;
++
++ printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
++ "Phillip Lougher\n");
++
++ if ((err = register_filesystem(&squashfs_fs_type)))
++ destroy_inodecache();
++
++out:
++ return err;
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++ unregister_filesystem(&squashfs_fs_type);
++ destroy_inodecache();
++}
++
++
++static struct kmem_cache * squashfs_inode_cachep;
++
++
++static struct inode *squashfs_alloc_inode(struct super_block *sb)
++{
++ struct squashfs_inode_info *ei;
++ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
++ if (!ei)
++ return NULL;
++ return &ei->vfs_inode;
++}
++
++
++static void squashfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
++}
++
++
++static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
++{
++ struct squashfs_inode_info *ei = foo;
++
++ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
++ SLAB_CTOR_CONSTRUCTOR)
++ inode_init_once(&ei->vfs_inode);
++}
++
++
++static int __init init_inodecache(void)
++{
++ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
++ sizeof(struct squashfs_inode_info),
++ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++ init_once, NULL);
++ if (squashfs_inode_cachep == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++
++static void destroy_inodecache(void)
++{
++ kmem_cache_destroy(squashfs_inode_cachep);
++}
++
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
++MODULE_LICENSE("GPL");
+diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
+new file mode 100644
+index 0000000..6f863f0
+--- /dev/null
++++ b/fs/squashfs/squashfs.h
+@@ -0,0 +1,87 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs.h
++ */
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#endif
++
++#ifdef SQUASHFS_TRACE
++#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
++#else
++#define TRACE(s, args...) {}
++#endif
++
++#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
++
++#define SERROR(s, args...) do { \
++ if (!silent) \
++ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
++ } while(0)
++
++#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
++
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
++{
++ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
++}
++
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
++#define SQSH_EXTERN
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index, int srclength);
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset);
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment);
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length);
++extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
++extern const struct address_space_operations squashfs_symlink_aops;
++extern const struct address_space_operations squashfs_aops;
++extern const struct address_space_operations squashfs_aops_4K;
++extern struct inode_operations squashfs_dir_inode_ops;
++#else
++#define SQSH_EXTERN static
++#endif
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
+diff --git a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c
+new file mode 100644
+index 0000000..d8d9d55
+--- /dev/null
++++ b/fs/squashfs/squashfs2_0.c
+@@ -0,0 +1,742 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs2_0.c
++ */
++
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/zlib.h>
++#include <linux/fs.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++
++#include "squashfs.h"
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
++ struct nameidata *);
++
++static struct file_operations squashfs_dir_ops_2 = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir_2
++};
++
++static struct inode_operations squashfs_dir_inode_ops_2 = {
++ .lookup = squashfs_lookup_2
++};
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static int read_fragment_index_table_2(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index_2,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ unsigned int fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
++ &msblk->fragment_index_2[i], 1);
++ msblk->fragment_index_2[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
++ struct squashfs_fragment_entry_2 fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry_2 sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
++ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ i->i_ino = ino;
++ i->i_mtime.tv_sec = sblk->mkfs_time;
++ i->i_atime.tv_sec = sblk->mkfs_time;
++ i->i_ctime.tv_sec = sblk->mkfs_time;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_nlink = 1;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++}
++
++
++static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
++{
++ struct super_block *s = i->i_sb;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ unsigned int ino = i->i_ino;
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header_2 id, sid;
++ struct squashfs_base_inode_header_2 *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ squashfs_new_inode(msblk, i, inodeb, ino);
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
++ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
++ long long frag_blk;
++ unsigned int frag_size = 0;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location_2(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %x, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
++ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header_2 *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header_2 *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
++ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ return 1;
++
++failed_read:
++ ERROR("Unable to read inode [%x:%x]\n", block, offset);
++
++failed_read1:
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 *index;
++ char *str;
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_index\n");
++ goto failure;
++ }
++
++ index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index_2),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ kfree(str);
++failure:
++ return length;
++}
++
++
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ struct squashfs_dir_entry_2 *dire;
++
++ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto finish;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos, SQUASHFS_MK_VFS_INODE(
++ dirh.start_block, dire->offset),
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ }
++ }
++
++finish:
++ kfree(dire);
++ return 0;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ kfree(dire);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ struct squashfs_dir_entry_2 *dire;
++ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
++
++ TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto exit_loop;
++ }
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (sorted && name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++ unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %lld\n", name,
++ dirh.start_block, dire->offset, ino);
++
++ inode = squashfs_iget(i->i_sb, ino, inode_number);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ kfree(dire);
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->read_inode = squashfs_read_inode_2;
++ msblk->read_fragment_index_table = read_fragment_index_table_2;
++
++ sblk->bytes_used = sblk->bytes_used_2;
++ sblk->uid_start = sblk->uid_start_2;
++ sblk->guid_start = sblk->guid_start_2;
++ sblk->inode_table_start = sblk->inode_table_start_2;
++ sblk->directory_table_start = sblk->directory_table_start_2;
++ sblk->fragment_table_start = sblk->fragment_table_start_2;
++
++ return 1;
++}
+diff --git a/include/linux/aufs_type.h b/include/linux/aufs_type.h
+new file mode 100755
+index 0000000..8b4629e
+--- /dev/null
++++ b/include/linux/aufs_type.h
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: aufs_type.h,v 1.55 2007/05/14 03:40:57 sfjro Exp $ */
++
++#include <linux/ioctl.h>
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#define AUFS_VERSION "20070514"
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++typedef char aufs_bindex_t;
++#define AUFS_BRANCH_MAX 127
++#else
++typedef short aufs_bindex_t;
++#ifdef CONFIG_AUFS_BRANCH_MAX_511
++#define AUFS_BRANCH_MAX 511
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++#define AUFS_BRANCH_MAX 1023
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++#define AUFS_BRANCH_MAX 32767
++#else
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif
++
++#define AUFS_NAME "aufs"
++#define AUFS_FSTYPE AUFS_NAME
++
++#define AUFS_ROOT_INO 2
++#define AUFS_FIRST_INO 11
++
++#define AUFS_WH_PFX ".wh."
++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
++#define AUFS_DIRWH_DEF 3
++#define AUFS_RDCACHE_DEF 10 /* seconds */
++#define AUFS_WKQ_NAME AUFS_NAME "d"
++#define AUFS_NWKQ_DEF 4
++
++#ifdef CONFIG_AUFS_COMPAT
++#define AUFS_DIROPQ_NAME "__dir_opaque"
++#else
++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#endif
++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++/* will be whiteouted doubly */
++#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME
++#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plink"
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {AuCtlErr, AuCtlErr_Last};
++enum {
++ AuCtl_REFRESH, //AuCtl_REFRESHV,
++ //AuCtl_FLUSH_PLINK,
++ //AuCtl_CPUP,
++ AuCtl_CPDOWN, AuCtl_MVDOWN
++};
++
++struct aufs_ctl_cp {
++ int bsrc, bdst;
++ int err;
++};
++
++#define Type 'A'
++#define AUFS_CTL_REFRESH _IO(Type, AuCtl_REFRESH)
++//#define AUFS_CTL_REFRESHV _IO(Type, AuCtl_REFRESHV)
++//#define AUFS_CTL_FLUSH_PLINK _IOR(Type, AuCtl_FLUSH_PLINK)
++//#define AUFS_CTL_CPUP _IOWR(Type, AuCtl_CPUP, struct aufs_ctl_cp)
++#define AUFS_CTL_CPDOWN _IOWR(Type, AuCtl_CPDOWN, struct aufs_ctl_cp)
++#define AUFS_CTL_MVDOWN _IOWR(Type, AuCtl_MVDOWN, struct aufs_ctl_cp)
++#undef Type
++
++#endif /* __AUFS_TYPE_H__ */
+diff --git a/include/linux/squashfs_fs.h b/include/linux/squashfs_fs.h
+new file mode 100644
+index 0000000..a9380ad
+--- /dev/null
++++ b/include/linux/squashfs_fs.h
+@@ -0,0 +1,934 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a) vmalloc(a)
++#define SQUASHFS_FREE(a) vfree(a)
++#else
++#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a) kfree(a)
++#endif
++#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
++#define SQUASHFS_MAJOR 3
++#define SQUASHFS_MINOR 0
++#define SQUASHFS_MAGIC 0x73717368
++#define SQUASHFS_MAGIC_SWAP 0x68737173
++#define SQUASHFS_START 0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE 8192
++#define SQUASHFS_METADATA_LOG 13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE 65536
++#define SQUASHFS_FILE_LOG 16
++
++#define SQUASHFS_FILE_MAX_SIZE 65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS 256
++#define SQUASHFS_GUIDS 255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN 256
++
++#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK ((long long) -1)
++#define SQUASHFS_USED_BLK ((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI 0
++#define SQUASHFS_NOD 1
++#define SQUASHFS_CHECK 2
++#define SQUASHFS_NOF 3
++#define SQUASHFS_NO_FRAG 4
++#define SQUASHFS_ALWAYS_FRAG 5
++#define SQUASHFS_DUPLICATE 6
++#define SQUASHFS_EXPORT 7
++
++#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_EXPORT)
++
++#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
++ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++ (duplicate_checking << 6) | (exportable << 7))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE 1
++#define SQUASHFS_FILE_TYPE 2
++#define SQUASHFS_SYMLINK_TYPE 3
++#define SQUASHFS_BLKDEV_TYPE 4
++#define SQUASHFS_CHRDEV_TYPE 5
++#define SQUASHFS_FIFO_TYPE 6
++#define SQUASHFS_SOCKET_TYPE 7
++#define SQUASHFS_LDIR_TYPE 8
++#define SQUASHFS_LREG_TYPE 9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES 5
++#define SQUASHFS_IPC_TYPE 0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT (1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops. Inodes consist of a compressed block number, and an
++ * uncompressed offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
++ << 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
++ ((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a) ((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
++ sizeof(long long))
++
++/* inode lookup table defines */
++#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
++
++#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
++ sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS 8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG 64
++
++#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
++ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE 0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES 31
++#define SQUASHFS_META_NUMBER 8
++#define SQUASHFS_SLOTS 4
++
++struct meta_entry {
++ long long data_block;
++ unsigned int index_block;
++ unsigned short offset;
++ unsigned short pad;
++};
++
++struct meta_index {
++ unsigned int inode_number;
++ unsigned int offset;
++ unsigned short entries;
++ unsigned short skip;
++ unsigned short locked;
++ unsigned short pad;
++ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long squashfs_block_t;
++typedef long long squashfs_inode_t;
++
++struct squashfs_super_block {
++ unsigned int s_magic;
++ unsigned int inodes;
++ unsigned int bytes_used_2;
++ unsigned int uid_start_2;
++ unsigned int guid_start_2;
++ unsigned int inode_table_start_2;
++ unsigned int directory_table_start_2;
++ unsigned int s_major:16;
++ unsigned int s_minor:16;
++ unsigned int block_size_1:16;
++ unsigned int block_log:16;
++ unsigned int flags:8;
++ unsigned int no_uids:8;
++ unsigned int no_guids:8;
++ unsigned int mkfs_time /* time of filesystem creation */;
++ squashfs_inode_t root_inode;
++ unsigned int block_size;
++ unsigned int fragments;
++ unsigned int fragment_table_start_2;
++ long long bytes_used;
++ long long uid_start;
++ long long guid_start;
++ long long inode_table_start;
++ long long directory_table_start;
++ long long fragment_table_start;
++ long long lookup_table_start;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++ unsigned int index;
++ unsigned int start_block;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER \
++ unsigned int inode_type:4; \
++ unsigned int mode:12; \
++ unsigned int uid:8; \
++ unsigned int guid:8; \
++ unsigned int mtime; \
++ unsigned int inode_number;
++
++struct squashfs_base_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ long long file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int parent_inode;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int i_count:16;
++ unsigned int parent_inode;
++ struct squashfs_dir_index index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header {
++ struct squashfs_base_inode_header base;
++ struct squashfs_dev_inode_header dev;
++ struct squashfs_symlink_inode_header symlink;
++ struct squashfs_reg_inode_header reg;
++ struct squashfs_lreg_inode_header lreg;
++ struct squashfs_dir_inode_header dir;
++ struct squashfs_ldir_inode_header ldir;
++ struct squashfs_ipc_inode_header ipc;
++};
++
++struct squashfs_dir_entry {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ int inode_number:16;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++ unsigned int count:8;
++ unsigned int start_block;
++ unsigned int inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++ long long start_block;
++ unsigned int size;
++ unsigned int pending;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa. These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++ int bits;\
++ int b_pos;\
++ unsigned long long val;\
++ unsigned char *s;\
++ unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ipc_inode_header))\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dev_inode_header)); \
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_symlink_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_reg_inode_header));\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_lreg_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ldir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++ SQUASHFS_SWAP((s)->index, d, 0, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++ SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++ SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 2);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 16)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 4);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 32)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 64)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * bits / 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ bits)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int type:4;
++ unsigned int offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++ SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_ipc_inode_header_1));\
++ SQUASHFS_SWAP((s)->type, d, 24, 4);\
++ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dev_inode_header_1));\
++ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_1));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_reg_inode_header_1));\
++ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dir_inode_header_1));\
++ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++ unsigned int index:27;
++ unsigned int start_block:29;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++ unsigned int i_count:16;
++ struct squashfs_dir_index_2 index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header_2 {
++ struct squashfs_base_inode_header_2 base;
++ struct squashfs_dev_inode_header_2 dev;
++ struct squashfs_symlink_inode_header_2 symlink;
++ struct squashfs_reg_inode_header_2 reg;
++ struct squashfs_dir_inode_header_2 dir;
++ struct squashfs_ldir_inode_header_2 ldir;
++ struct squashfs_ipc_inode_header_2 ipc;
++};
++
++struct squashfs_dir_header_2 {
++ unsigned int count:8;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++ unsigned int start_block;
++ unsigned int size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dev_inode_header_2)); \
++ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_2));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_reg_inode_header_2));\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_ldir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++ SQUASHFS_SWAP((s)->index, d, 0, 27);\
++ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++ SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++ SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++ sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++ /* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, b_pos)
++#else
++ /* convert from big endian to little endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++ b_pos = pos % 8;\
++ val = 0;\
++ s = (unsigned char *)p + (pos / 8);\
++ d = ((unsigned char *) &val) + 7;\
++ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++ *d-- = *s++;\
++ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
++
++#endif
++#endif
+diff --git a/include/linux/squashfs_fs_i.h b/include/linux/squashfs_fs_i.h
+new file mode 100644
+index 0000000..798891a
+--- /dev/null
++++ b/include/linux/squashfs_fs_i.h
+@@ -0,0 +1,45 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_i.h
++ */
++
++struct squashfs_inode_info {
++ long long start_block;
++ unsigned int offset;
++ union {
++ struct {
++ long long fragment_start_block;
++ unsigned int fragment_size;
++ unsigned int fragment_offset;
++ long long block_list_start;
++ } s1;
++ struct {
++ long long directory_index_start;
++ unsigned int directory_index_offset;
++ unsigned int directory_index_count;
++ unsigned int parent_inode;
++ } s2;
++ } u;
++ struct inode vfs_inode;
++};
++#endif
+diff --git a/include/linux/squashfs_fs_sb.h b/include/linux/squashfs_fs_sb.h
+new file mode 100644
+index 0000000..8f3bf99
+--- /dev/null
++++ b/include/linux/squashfs_fs_sb.h
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++ long long block;
++ int length;
++ long long next_index;
++ char *data;
++};
++
++struct squashfs_fragment_cache {
++ long long block;
++ int length;
++ unsigned int locked;
++ char *data;
++};
++
++struct squashfs_sb_info {
++ struct squashfs_super_block sblk;
++ int devblksize;
++ int devblksize_log2;
++ int swap;
++ struct squashfs_cache *block_cache;
++ struct squashfs_fragment_cache *fragment;
++ int next_cache;
++ int next_fragment;
++ int next_meta_index;
++ unsigned int *uid;
++ unsigned int *guid;
++ long long *fragment_index;
++ unsigned int *fragment_index_2;
++ char *read_page;
++ struct mutex read_data_mutex;
++ struct mutex read_page_mutex;
++ struct mutex block_cache_mutex;
++ struct mutex fragment_mutex;
++ struct mutex meta_index_mutex;
++ wait_queue_head_t waitq;
++ wait_queue_head_t fragment_wait_queue;
++ struct meta_index *meta_index;
++ z_stream stream;
++ long long *inode_lookup_table;
++ int (*read_inode)(struct inode *i, squashfs_inode_t \
++ inode);
++ long long (*read_blocklist)(struct inode *inode, int \
++ index, int readahead_blks, char *block_list, \
++ unsigned short **block_p, unsigned int *bsize);
++ int (*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+diff --git a/init/Kconfig b/init/Kconfig
+index b170aa1..bcfc3b4 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -244,23 +244,21 @@ config AUDITSYSCALL
+ ensure that INOTIFY is configured.
+
+ config IKCONFIG
+- tristate "Kernel .config support"
++ tristate "Kernel .miniconfig support"
+ ---help---
+- This option enables the complete Linux kernel ".config" file
++ This option enables the mini Linux kernel ".miniconfig" file
+ contents to be saved in the kernel. It provides documentation
+ of which kernel options are used in a running kernel or in an
+- on-disk kernel. This information can be extracted from the kernel
+- image file with the script scripts/extract-ikconfig and used as
+- input to rebuild the current kernel or to build another kernel.
+- It can also be extracted from a running kernel by reading
+- /proc/config.gz if enabled (below).
++ on-disk kernel.
++ It can be extracted from a running kernel by reading
++ /proc/miniconfig.gz if enabled (below).
+
+ config IKCONFIG_PROC
+- bool "Enable access to .config through /proc/config.gz"
++ bool "Enable access to .miniconfig through /proc/miniconfig.gz"
+ depends on IKCONFIG && PROC_FS
+ ---help---
+ This option enables access to the kernel configuration file
+- through /proc/config.gz.
++ through /proc/miniconfig.gz.
+
+ config CPUSETS
+ bool "Cpuset support"
+diff --git a/init/LzmaDecode.c b/init/LzmaDecode.c
+new file mode 100644
+index 0000000..21bf40b
+--- /dev/null
++++ b/init/LzmaDecode.c
+@@ -0,0 +1,588 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder (optimized for Speed version)
++
++ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this Code, expressly permits you to
++ statically or dynamically link your Code (or bind by name) to the
++ interfaces of this file without subjecting your linked Code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_READ_BYTE (*Buffer++)
++
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
++
++#ifdef _LZMA_IN_CB
++
++#define RC_TEST { if (Buffer == BufferLim) \
++ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
++
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
++
++#else
++
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
++
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
++
++#endif
++
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
++
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
++
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
++ { UpdateBit0(p); mi <<= 1; A0; } else \
++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
++
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
++
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
++ { int i = numLevels; res = 1; \
++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
++ res -= (1 << numLevels); }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
++{
++ unsigned char prop0;
++ if (size < LZMA_PROPERTIES_SIZE)
++ return LZMA_RESULT_DATA_ERROR;
++ prop0 = propsData[0];
++ if (prop0 >= (9 * 5 * 5))
++ return LZMA_RESULT_DATA_ERROR;
++ {
++ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
++ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
++ propsRes->lc = prop0;
++ /*
++ unsigned char remainder = (unsigned char)(prop0 / 9);
++ propsRes->lc = prop0 % 9;
++ propsRes->pb = remainder / 5;
++ propsRes->lp = remainder % 5;
++ */
++ }
++
++ #ifdef _LZMA_OUT_READ
++ {
++ int i;
++ propsRes->DictionarySize = 0;
++ for (i = 0; i < 4; i++)
++ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
++ if (propsRes->DictionarySize == 0)
++ propsRes->DictionarySize = 1;
++ }
++ #endif
++ return LZMA_RESULT_OK;
++}
++
++#define kLzmaStreamWasFinishedId (-1)
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
++{
++ CProb *p = vs->Probs;
++ SizeT nowPos = 0;
++ Byte previousByte = 0;
++ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
++ int lc = vs->Properties.lc;
++
++ #ifdef _LZMA_OUT_READ
++
++ UInt32 Range = vs->Range;
++ UInt32 Code = vs->Code;
++ #ifdef _LZMA_IN_CB
++ const Byte *Buffer = vs->Buffer;
++ const Byte *BufferLim = vs->BufferLim;
++ #else
++ const Byte *Buffer = inStream;
++ const Byte *BufferLim = inStream + inSize;
++ #endif
++ int state = vs->State;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++ UInt32 distanceLimit = vs->DistanceLimit;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->Properties.DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ Byte tempDictionary[4];
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++ if (len == kLzmaStreamWasFinishedId)
++ return LZMA_RESULT_OK;
++
++ if (dictionarySize == 0)
++ {
++ dictionary = tempDictionary;
++ dictionarySize = 1;
++ tempDictionary[0] = vs->TempDictionary[0];
++ }
++
++ if (len == kLzmaNeedInitId)
++ {
++ {
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ UInt32 i;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ rep0 = rep1 = rep2 = rep3 = 1;
++ state = 0;
++ globalPos = 0;
++ distanceLimit = 0;
++ dictionaryPos = 0;
++ dictionary[dictionarySize - 1] = 0;
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++ }
++ len = 0;
++ }
++ while(len != 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++
++ #else /* if !_LZMA_OUT_READ */
++
++ int state = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ int len = 0;
++ const Byte *Buffer;
++ const Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++
++ {
++ UInt32 i;
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ }
++
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++
++ #endif /* _LZMA_OUT_READ */
++
++ while(nowPos < outSize)
++ {
++ CProb *prob;
++ UInt32 bound;
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++
++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ int symbol = 1;
++ UpdateBit0(prob)
++ prob = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state >= kNumLitStates)
++ {
++ int matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ do
++ {
++ int bit;
++ CProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & 0x100);
++ probLit = prob + 0x100 + bit + symbol;
++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
++ }
++ while (symbol < 0x100);
++ }
++ while (symbol < 0x100)
++ {
++ CProb *probLit = prob + symbol;
++ RC_GET_BIT(probLit, symbol)
++ }
++ previousByte = (Byte)symbol;
++
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRep + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < kNumLitStates ? 0 : 3;
++ prob = p + LenCoder;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG0 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ UpdateBit0(prob);
++
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit == 0)
++ #else
++ if (nowPos == 0)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ state = state < kNumLitStates ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++ #endif
++
++ continue;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ UpdateBit1(prob);
++ prob = p + IsRepG1 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep1;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG2 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep2;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ state = state < kNumLitStates ? 8 : 11;
++ prob = p + RepLenCoder;
++ }
++ {
++ int numBits, offset;
++ CProb *probLen = prob + LenChoice;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ numBits = kLenNumLowBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenChoice2;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ numBits = kLenNumMidBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ numBits = kLenNumHighBits;
++ }
++ }
++ RangeDecoderBitTreeDecode(probLen, numBits, len);
++ len += offset;
++ }
++
++ if (state < 4)
++ {
++ int posSlot;
++ state += kNumLitStates;
++ prob = p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits);
++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = (2 | ((UInt32)posSlot & 1));
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 <<= numDirectBits;
++ prob = p + SpecPos + rep0 - posSlot - 1;
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ RC_NORMALIZE
++ Range >>= 1;
++ rep0 <<= 1;
++ if (Code >= Range)
++ {
++ Code -= Range;
++ rep0 |= 1;
++ }
++ }
++ while (--numDirectBits != 0);
++ prob = p + Align;
++ rep0 <<= kNumAlignBits;
++ numDirectBits = kNumAlignBits;
++ }
++ {
++ int i = 1;
++ int mi = 1;
++ do
++ {
++ CProb *prob3 = prob + mi;
++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
++ i <<= 1;
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ else
++ rep0 = posSlot;
++ if (++rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = kLzmaStreamWasFinishedId;
++ break;
++ }
++ }
++
++ len += kMatchMinLen;
++ #ifdef _LZMA_OUT_READ
++ if (rep0 > distanceLimit)
++ #else
++ if (rep0 > nowPos)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ #ifdef _LZMA_OUT_READ
++ if (dictionarySize - distanceLimit > (UInt32)len)
++ distanceLimit += len;
++ else
++ distanceLimit = dictionarySize;
++ #endif
++
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ len--;
++ outStream[nowPos++] = previousByte;
++ }
++ while(len != 0 && nowPos < outSize);
++ }
++ }
++ RC_NORMALIZE;
++
++ #ifdef _LZMA_OUT_READ
++ vs->Range = Range;
++ vs->Code = Code;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + (UInt32)nowPos;
++ vs->DistanceLimit = distanceLimit;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->RemainLen = len;
++ vs->TempDictionary[0] = tempDictionary[0];
++ #endif
++
++ #ifdef _LZMA_IN_CB
++ vs->Buffer = Buffer;
++ vs->BufferLim = BufferLim;
++ #else
++ *inSizeProcessed = (SizeT)(Buffer - inStream);
++ #endif
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff --git a/init/LzmaDecode.h b/init/LzmaDecode.h
+new file mode 100644
+index 0000000..213062a
+--- /dev/null
++++ b/init/LzmaDecode.h
+@@ -0,0 +1,131 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++/* #define _LZMA_SYSTEM_SIZE_T */
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifndef SizeT
++#ifdef _LZMA_SYSTEM_SIZE_T
++#include <stddef.h>
++#define SizeT size_t
++#else
++#define SizeT UInt32
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_PROPERTIES_SIZE 5
++
++typedef struct _CLzmaProperties
++{
++ int lc;
++ int lp;
++ int pb;
++ #ifdef _LZMA_OUT_READ
++ UInt32 DictionarySize;
++ #endif
++}CLzmaProperties;
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
++
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
++
++#define kLzmaNeedInitId (-2)
++
++typedef struct _CLzmaDecoderState
++{
++ CLzmaProperties Properties;
++ CProb *Probs;
++
++ #ifdef _LZMA_IN_CB
++ const unsigned char *Buffer;
++ const unsigned char *BufferLim;
++ #endif
++
++ #ifdef _LZMA_OUT_READ
++ unsigned char *Dictionary;
++ UInt32 Range;
++ UInt32 Code;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 DistanceLimit;
++ UInt32 Reps[4];
++ int State;
++ int RemainLen;
++ unsigned char TempDictionary[4];
++ #endif
++} CLzmaDecoderState;
++
++#ifdef _LZMA_OUT_READ
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
++#endif
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
++
++#endif
+diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
+index ed652f4..5fd1ec5 100644
+--- a/init/do_mounts_rd.c
++++ b/init/do_mounts_rd.c
+@@ -5,7 +5,9 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+ #include <linux/cramfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/initrd.h>
++#include <linux/vmalloc.h>
+ #include <linux/string.h>
+
+ #include "do_mounts.h"
+@@ -31,6 +33,9 @@ static int __init ramdisk_start_setup(char *str)
+ __setup("ramdisk_start=", ramdisk_start_setup);
+
+ static int __init crd_load(int in_fd, int out_fd);
++#ifdef CONFIG_LZMA_INITRD
++static int __init lzma_rd_load(int in_fd, int out_fd);
++#endif
+
+ /*
+ * This routine tries to find a RAM disk image to load, and returns the
+@@ -39,6 +44,7 @@ static int __init crd_load(int in_fd, int out_fd);
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
++ * squashfs
+ * minix
+ * ext2
+ * romfs
+@@ -53,6 +59,7 @@ identify_ramdisk_image(int fd, int start_block)
+ struct ext2_super_block *ext2sb;
+ struct romfs_super_block *romfsb;
+ struct cramfs_super *cramfsb;
++ struct squashfs_super_block *squashfsb;
+ int nblocks = -1;
+ unsigned char *buf;
+
+@@ -64,6 +71,7 @@ identify_ramdisk_image(int fd, int start_block)
+ ext2sb = (struct ext2_super_block *) buf;
+ romfsb = (struct romfs_super_block *) buf;
+ cramfsb = (struct cramfs_super *) buf;
++ squashfsb = (struct squashfs_super_block *) buf;
+ memset(buf, 0xe5, size);
+
+ /*
+@@ -82,6 +90,17 @@ identify_ramdisk_image(int fd, int start_block)
+ nblocks = 0;
+ goto done;
+ }
++ /*
++ * handle lzma compressed initrd, returns nblocks=1 as indication
++ */
++ if( buf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0 && buf[11] == 0
++ && buf[12] == 0 )
++ {
++ printk( KERN_NOTICE "RAMDISK: LZMA image found at block %d\n",
++ start_block);
++ nblocks = 1; // just a convenient return flag
++ goto done;
++ }
+
+ /* romfs is at block zero too */
+ if (romfsb->word0 == ROMSB_WORD0 &&
+@@ -101,6 +120,18 @@ identify_ramdisk_image(int fd, int start_block)
+ goto done;
+ }
+
++ /* squashfs is at block zero too */
++ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++ printk(KERN_NOTICE
++ "RAMDISK: squashfs filesystem found at block %d\n",
++ start_block);
++ if (squashfsb->s_major < 3)
++ nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ else
++ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ goto done;
++ }
++
+ /*
+ * Read block 1 to test for minix and ext2 superblock
+ */
+@@ -172,7 +203,22 @@ int __init rd_load_image(char *from)
+ #endif
+ goto done;
+ }
+-
++#ifdef CONFIG_LZMA_INITRD
++ /*
++ * handle lzma compressed image
++ */
++ if ( nblocks == 1 )
++ {
++ nblocks = 0;
++ if ( lzma_rd_load(in_fd, out_fd) == 0 )
++ {
++ printk("\nLZMA initrd loaded successfully\n");
++ goto successful_load;
++ }
++ printk(KERN_NOTICE "LZMA initrd is not in the correct format\n");
++ goto done;
++ }
++#endif
+ /*
+ * NOTE NOTE: nblocks is not actually blocks but
+ * the number of kibibytes of data to load into a ramdisk.
+@@ -393,6 +439,134 @@ static void __init error(char *x)
+ unzip_error = 1;
+ }
+
++#ifdef CONFIG_LZMA_INITRD
++#define _LZMA_IN_CB
++#define _LZMA_OUT_READ
++#include "LzmaDecode.h"
++#include "LzmaDecode.c"
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
++
++/*
++ * Do the lzma decompression
++ */
++static int __init lzma_rd_load(int in_fd, int out_fd)
++{
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned char* outputbuffer;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++ unsigned int kBlockSize = 0x10000;
++ unsigned int nowPos = 0;
++ unsigned int outsizeProcessed = 0;
++ int res;
++ ILzmaInCallback callback;
++
++ insize = 0; /* valid bytes in inbuf */
++ inptr = 0; /* index of next byte to be processed in inbuf */
++ exit_code = 0;
++ crd_infd = in_fd;
++ inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
++ if (inbuf == 0)
++ {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma input buffer\n");
++ return -1;
++ }
++
++ callback.Read = read_byte;
++
++ /* lzma args */
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ /* read dictionary size */
++ p = (char*)&state.Properties.DictionarySize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ /* get uncompressedSize */
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ /* skip big file */
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ printk( KERN_NOTICE "RAMDISK: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
++ state.Properties.lc, state.Properties.lp, state.Properties.pb, state.Properties.DictionarySize, uncompressedSize);
++ outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
++ if (outputbuffer == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma output buffer\n");
++ return -1;
++ }
++
++ state.Probs = (CProb*)kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
++ if ( state.Probs == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma workspace\n");
++ return -1;
++ }
++
++#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
++ state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
++#else
++ state.Dictionary = vmalloc( state.Properties.DictionarySize);
++#endif
++ if ( state.Dictionary == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma dictionary\n");
++ return -1;
++ }
++
++ printk( KERN_NOTICE "LZMA initrd by Ming-Ching Tiew <mctiew@yahoo.com> " );
++
++ LzmaDecoderInit( &state );
++
++ for( nowPos =0; nowPos < uncompressedSize ; )
++ {
++ UInt32 blockSize = uncompressedSize - nowPos;
++ if( blockSize > kBlockSize)
++ blockSize = kBlockSize;
++ res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
++ if( res != 0 ) {
++ printk( KERN_ERR "RAMDISK: Lzma decode failure\n");
++ return -1;
++ }
++ if( outsizeProcessed == 0 )
++ {
++ uncompressedSize = nowPos;
++ printk( KERN_NOTICE "RAMDISK nowPos=%d, uncompressedSize=%d\n",
++ nowPos, uncompressedSize );
++ break;
++ }
++ sys_write(out_fd, outputbuffer, outsizeProcessed );
++ nowPos += outsizeProcessed;
++ printk( ".");
++ }
++
++#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
++ kfree(state.Dictionary);
++#else
++ vfree(state.Dictionary);
++#endif
++ kfree(inbuf);
++ kfree(outputbuffer);
++ kfree(state.Probs);
++ return 0;
++}
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++#endif /*CONFIG_LZMA_INITRD*/
++
+ static int __init crd_load(int in_fd, int out_fd)
+ {
+ int result;
+diff --git a/init/initramfs.c b/init/initramfs.c
+index 00eff7a..30d32a2 100644
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -6,6 +6,7 @@
+ #include <linux/delay.h>
+ #include <linux/string.h>
+ #include <linux/syscalls.h>
++#include <linux/vmalloc.h>
+
+ static __initdata char *message;
+ static void __init error(char *x)
+@@ -441,6 +442,118 @@ static void __init flush_window(void)
+ outcnt = 0;
+ }
+
++#ifdef CONFIG_LZMA_INITRAM_FS
++#define _LZMA_IN_CB
++#define _LZMA_OUT_READ
++#include "LzmaDecode.h"
++#ifndef CONFIG_LZMA_INITRD
++ #include "LzmaDecode.c"
++#endif
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++static int __init lzma_unzip(void)
++{
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned char* outputbuffer;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++ unsigned int kBlockSize = 0x10000;
++ unsigned int nowPos = 0;
++ unsigned int outsizeProcessed = 0;
++ int res;
++ ILzmaInCallback callback;
++
++ callback.Read = read_byte;
++
++ // lzma args
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ // read dictionary size
++ p = (char*)&state.Properties.DictionarySize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // get uncompressedSize
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // skip big file
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
++ state.Properties.lc,state.Properties.lp,state.Properties.pb,state.Properties.DictionarySize, uncompressedSize);
++ outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
++ if (outputbuffer == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
++ return -1;
++ }
++
++ state.Probs = (CProb*) kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
++ if ( state.Probs == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
++ return -1;
++ }
++
++#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
++ state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
++#else
++ state.Dictionary = vmalloc( state.Properties.DictionarySize);
++#endif
++ if ( state.Dictionary == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma dictionary\n");
++ return -1;
++ }
++
++ printk( KERN_NOTICE "LZMA initramfs by Ming-Ching Tiew <mctiew@yahoo.com> " );
++
++ LzmaDecoderInit( &state );
++
++ for( nowPos =0; nowPos < uncompressedSize ; )
++ {
++ UInt32 blockSize = uncompressedSize - nowPos;
++ if( blockSize > kBlockSize)
++ blockSize = kBlockSize;
++ res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
++ if( res != 0 ) {
++ panic( KERN_ERR "initramfs: Lzma decode failure\n");
++ return -1;
++ }
++ if( outsizeProcessed == 0 )
++ {
++ uncompressedSize = nowPos;
++ printk( KERN_NOTICE "initramfs: nowPos=%d, uncompressedSize=%d\n",
++ nowPos, uncompressedSize );
++ break;
++ }
++ flush_buffer(outputbuffer, outsizeProcessed);
++ nowPos += outsizeProcessed;
++ printk( ".");
++ }
++
++#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
++ kfree(state.Dictionary);
++#else
++ vfree(state.Dictionary);
++#endif
++ kfree(outputbuffer);
++ kfree(state.Probs);
++ return 0;
++}
++
++#endif /*CONFIG LZMA_INITRAM_FS*/
++
+ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ {
+ int written;
+@@ -475,12 +588,31 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ inptr = 0;
+ outcnt = 0; /* bytes in output buffer */
+ bytes_out = 0;
+- crc = (ulg)0xffffffffL; /* shift register contents */
+- makecrc();
+- gunzip();
+- if (state != Reset)
++ if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
++ {
++ printk( KERN_NOTICE "detected gzip initramfs\n");
++ crc = (ulg)0xffffffffL; /* shift register contents */
++ makecrc();
++ gunzip();
++ if (state != Reset)
+ error("junk in gzipped archive");
+- this_header = saved_offset + inptr;
++ }
++#ifdef CONFIG_LZMA_INITRAM_FS
++ else if( inbuf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0
++ && buf[11] == 0 && buf[12] == 0 )
++ {
++ printk( KERN_NOTICE "detected lzma initramfs\n");
++ lzma_unzip();
++ }
++#endif
++ else
++ {
++ // skip forward ?
++ crc = (ulg)0xffffffffL; /* shift register contents */
++ makecrc();
++ gunzip();
++ }
++ this_header = saved_offset + inptr;
+ buf += inptr;
+ len -= inptr;
+ }
+diff --git a/kernel/Makefile b/kernel/Makefile
+index ac6b27a..bd498a2 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -66,7 +66,7 @@ $(obj)/configs.o: $(obj)/config_data.h
+ # config_data.h contains the same information as ikconfig.h but gzipped.
+ # Info from config_data can be extracted from /proc/config*
+ targets += config_data.gz
+-$(obj)/config_data.gz: .config FORCE
++$(obj)/config_data.gz: .miniconfig FORCE
+ $(call if_changed,gzip)
+
+ quiet_cmd_ikconfiggz = IKCFG $@
+diff --git a/kernel/configs.c b/kernel/configs.c
+index 8fa1fb2..c8407eb 100644
+--- a/kernel/configs.c
++++ b/kernel/configs.c
+@@ -88,7 +88,7 @@ static int __init ikconfig_init(void)
+ struct proc_dir_entry *entry;
+
+ /* create the current config file */
+- entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
++ entry = create_proc_entry("miniconfig.gz", S_IFREG | S_IRUGO,
+ &proc_root);
+ if (!entry)
+ return -ENOMEM;
+@@ -104,7 +104,7 @@ static int __init ikconfig_init(void)
+
+ static void __exit ikconfig_cleanup(void)
+ {
+- remove_proc_entry("config.gz", &proc_root);
++ remove_proc_entry("miniconfig.gz", &proc_root);
+ }
+
+ module_init(ikconfig_init);
+diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
+index fe5c7db..a5150e6 100644
+--- a/kernel/time/clocksource.c
++++ b/kernel/time/clocksource.c
+@@ -85,8 +85,8 @@ static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
+ if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
+ return;
+
+- printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
+- cs->name, delta);
++/* printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
++ cs->name, delta); */
+ cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
+ clocksource_change_rating(cs, 0);
+ cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
+diff --git a/kernel/timer.c b/kernel/timer.c
+index dd6c2c1..3a8f485 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -916,8 +916,8 @@ static void change_clocksource(void)
+
+ tick_clock_notify();
+
+- printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+- clock->name);
++/* printk(KERN_INFO "Time: %s clocksource has been installed.\n",
++ clock->name); */
+ }
+ #else
+ static inline void change_clocksource(void) { }
+diff --git a/miniconfig.sh b/miniconfig.sh
+new file mode 100755
+index 0000000..28e7433
+--- /dev/null
++++ b/miniconfig.sh
+@@ -0,0 +1,2 @@
++#!/bin/sh -f
++make allnoconfig KCONFIG_ALLCONFIG=.miniconfig
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index fc498fe..e98172c 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -162,4 +162,9 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
+ quiet_cmd_gzip = GZIP $@
+ cmd_gzip = gzip -f -9 < $< > $@
+
++# LZMA
++#
++quiet_cmd_lzma = LZMA $@
++cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++
+
+diff --git a/scripts/gen_lzma_initramfs_list.sh b/scripts/gen_lzma_initramfs_list.sh
+new file mode 100644
+index 0000000..be3ed6a
+--- /dev/null
++++ b/scripts/gen_lzma_initramfs_list.sh
+@@ -0,0 +1,292 @@
++#!/bin/bash
++# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
++# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
++#
++# Released under the terms of the GNU GPL
++#
++# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
++# the cpio archive, and gzip to pack it.
++# The script may also be used to generate the inputfile used for gen_init_cpio
++# This script assumes that gen_init_cpio is located in usr/ directory
++
++# error out on errors
++set -e
++
++usage() {
++cat << EOF
++Usage:
++$0 [-o <file>] [-u <uid>] [-g <gid>] { -s | -d | <cpio_source>} ...
++ -o <file> Create lzma initramfs file named <file> using
++ gen_init_cpio and lzma
++ -u <uid> User ID to map to user ID 0 (root).
++ <uid> is only meaningful if <cpio_source>
++ is a directory.
++ -g <gid> Group ID to map to group ID 0 (root).
++ <gid> is only meaningful if <cpio_source>
++ is a directory.
++ <cpio_source> File list or directory for cpio archive.
++ If <cpio_source> is a .cpio file it will be used
++ as direct input to initramfs.
++ -s Create lzma file with small dictionary size
++ -d Output the default cpio list.
++
++All options except -o and -l may be repeated and are interpreted
++sequentially and immediately. -u and -g states are preserved across
++<cpio_source> options so an explicit "-u 0 -g 0" is required
++to reset the root/group mapping.
++EOF
++}
++
++list_default_initramfs() {
++ # echo usr/kinit/kinit
++ :
++}
++
++default_initramfs() {
++ cat <<-EOF >> ${output}
++ # This is a very simple, default initramfs
++
++ dir /dev 0755 0 0
++ nod /dev/console 0600 0 0 c 5 1
++ dir /root 0700 0 0
++ # file /kinit usr/kinit/kinit 0755 0 0
++ # slink /init kinit 0755 0 0
++ EOF
++}
++
++filetype() {
++ local argv1="$1"
++
++ # symlink test must come before file test
++ if [ -L "${argv1}" ]; then
++ echo "slink"
++ elif [ -f "${argv1}" ]; then
++ echo "file"
++ elif [ -d "${argv1}" ]; then
++ echo "dir"
++ elif [ -b "${argv1}" -o -c "${argv1}" ]; then
++ echo "nod"
++ elif [ -p "${argv1}" ]; then
++ echo "pipe"
++ elif [ -S "${argv1}" ]; then
++ echo "sock"
++ else
++ echo "invalid"
++ fi
++ return 0
++}
++
++list_print_mtime() {
++ :
++}
++
++print_mtime() {
++ local my_mtime="0"
++
++ if [ -e "$1" ]; then
++ my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
++ fi
++
++ echo "# Last modified: ${my_mtime}" >> ${output}
++ echo "" >> ${output}
++}
++
++list_parse() {
++ echo "$1 \\"
++}
++
++# for each file print a line in following format
++# <filetype> <name> <path to file> <octal mode> <uid> <gid>
++# for links, devices etc the format differs. See gen_init_cpio for details
++parse() {
++ local location="$1"
++ local name="${location/${srcdir}//}"
++ # change '//' into '/'
++ name="${name//\/\///}"
++ local mode="$2"
++ local uid="$3"
++ local gid="$4"
++ local ftype=$(filetype "${location}")
++ # remap uid/gid to 0 if necessary
++ [ "$uid" -eq "$root_uid" ] && uid=0
++ [ "$gid" -eq "$root_gid" ] && gid=0
++ local str="${mode} ${uid} ${gid}"
++
++ [ "${ftype}" == "invalid" ] && return 0
++ [ "${location}" == "${srcdir}" ] && return 0
++
++ case "${ftype}" in
++ "file")
++ str="${ftype} ${name} ${location} ${str}"
++ ;;
++ "nod")
++ local dev_type=
++ local maj=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{sub(/,/, "", $5); print $5}')
++ local min=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{print $6}')
++
++ if [ -b "${location}" ]; then
++ dev_type="b"
++ else
++ dev_type="c"
++ fi
++ str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
++ ;;
++ "slink")
++ local target=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{print $11}')
++ str="${ftype} ${name} ${target} ${str}"
++ ;;
++ *)
++ str="${ftype} ${name} ${str}"
++ ;;
++ esac
++
++ echo "${str}" >> ${output}
++
++ return 0
++}
++
++unknown_option() {
++ printf "ERROR: unknown option \"$arg\"\n" >&2
++ printf "If the filename validly begins with '-', " >&2
++ printf "then it must be prefixed\n" >&2
++ printf "by './' so that it won't be interpreted as an option." >&2
++ printf "\n" >&2
++ usage >&2
++ exit 1
++}
++
++list_header() {
++ :
++}
++
++header() {
++ printf "\n#####################\n# $1\n" >> ${output}
++}
++
++# process one directory (incl sub-directories)
++dir_filelist() {
++ ${dep_list}header "$1"
++
++ srcdir=$(echo "$1" | sed -e 's://*:/:g')
++ dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
++
++ # If $dirlist is only one line, then the directory is empty
++ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
++ ${dep_list}print_mtime "$1"
++
++ echo "${dirlist}" | \
++ while read x; do
++ ${dep_list}parse ${x}
++ done
++ fi
++}
++
++# if only one file is specified and it is .cpio file then use it direct as fs
++# if a directory is specified then add all files in given direcotry to fs
++# if a regular file is specified assume it is in gen_initramfs format
++input_file() {
++ source="$1"
++ if [ -f "$1" ]; then
++ ${dep_list}header "$1"
++ is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
++ if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
++ cpio_file=$1
++ [ ! -z ${dep_list} ] && echo "$1"
++ return 0
++ fi
++ if [ -z ${dep_list} ]; then
++ print_mtime "$1" >> ${output}
++ cat "$1" >> ${output}
++ else
++ cat "$1" | while read type dir file perm ; do
++ if [ "$type" == "file" ]; then
++ echo "$file \\";
++ fi
++ done
++ fi
++ elif [ -d "$1" ]; then
++ dir_filelist "$1"
++ else
++ echo " ${prog}: Cannot open '$1'" >&2
++ exit 1
++ fi
++}
++
++prog=$0
++root_uid=0
++root_gid=0
++dep_list=
++cpio_file=
++cpio_list=
++output="/dev/stdout"
++output_file=""
++opt=""
++
++arg="$1"
++case "$arg" in
++ "-l") # files included in initramfs - used by kbuild
++ dep_list="list_"
++ echo "deps_initramfs := \\"
++ shift
++ ;;
++ "-o") # generate lzma-ed cpio image named $1
++ shift
++ output_file="$1"
++ cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
++ output=${cpio_list}
++ shift
++ ;;
++esac
++while [ $# -gt 0 ]; do
++ arg="$1"
++ shift
++ case "$arg" in
++ "-u") # map $1 to uid=0 (root)
++ root_uid="$1"
++ shift
++ ;;
++ "-g") # map $1 to gid=0 (root)
++ root_gid="$1"
++ shift
++ ;;
++ "-s")
++ opt="-d16"
++ ;;
++ "-d") # display default initramfs list
++ default_list="$arg"
++ ${dep_list}default_initramfs
++ ;;
++ "-h")
++ usage
++ exit 0
++ ;;
++ *)
++ case "$arg" in
++ "-"*)
++ unknown_option
++ ;;
++ *) # input file/dir - process it
++ input_file "$arg" "$#"
++ ;;
++ esac
++ ;;
++ esac
++done
++
++# If output_file is set we will generate cpio archive and lzma it
++# we are carefull to delete tmp files
++if [ ! -z ${output_file} ]; then
++ if [ -z ${cpio_file} ]; then
++ cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
++ usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
++ else
++ cpio_tfile=${cpio_file}
++ fi
++ rm ${cpio_list}
++ lzma e ${cpio_tfile} ${output_file} ${opt}
++ [ -z ${cpio_file} ] && rm ${cpio_tfile}
++fi
++exit 0
+diff --git a/shrinkconfig.sh b/shrinkconfig.sh
+new file mode 100755
+index 0000000..e7a3df7
+--- /dev/null
++++ b/shrinkconfig.sh
+@@ -0,0 +1,79 @@
++#! /bin/bash
++
++# shrinkconfig copyright 2006 by Rob Landley <rob@landley.net>
++# Licensed under the GNU General Public License version 2.
++
++if [ $# -ne 1 ]
++then
++ echo "Turns current .config into a miniconfig file."
++ echo "Usage: shrinkconfig mini.config"
++ exit 1
++fi
++
++if [ ! -f .config ]
++then
++ echo "Need a .config file to shrink."
++ exit 1
++fi
++LENGTH=$(wc -l < .config)
++
++OUTPUT="$1"
++cp .config "$OUTPUT"
++if [ $? -ne 0 ]
++then
++ echo "Couldn't create $OUTPUT"
++ exit 1
++fi
++
++# If we get interrupted, clean up the mess
++
++KERNELOUTPUT=""
++
++function cleanup
++{
++ echo
++ echo "Interrupted."
++ [ ! -z "$KERNELOUTPUT" ] && rm -rf "$KERNELOUTPUT"
++ rm "$OUTPUT"
++ exit 1
++}
++
++trap cleanup HUP INT QUIT TERM
++
++# Since the "O=" argument to make doesn't work recursively, we need to jump
++# through a few hoops to avoid overwriting the .config that we're shrinking.
++
++# If we're building out of tree, we'll have absolute paths to source and build
++# directories in the Makefile.
++
++KERNELSRC=$(sed -n -e 's/KERNELSRC[^/]*:=[^/]*//p' Makefile)
++[ -z "$KERNELSRC" ] && KERNELSRC=$(pwd)
++KERNELOUTPUT=`pwd`/.config.minitemp
++
++mkdir -p "$KERNELOUTPUT" || exit 1
++
++echo "Shrinking .config to $OUTPUT..."
++
++for I in $(seq 1 $LENGTH)
++do
++ echo -n -e "\r"$I/$LENGTH lines $(wc -c < "$OUTPUT") bytes
++
++ sed -n "${I}!p" "$OUTPUT" > "$KERNELOUTPUT"/.config.test
++ # Do a config with this file
++ make -C "$KERNELSRC" O="$KERNELOUTPUT" allnoconfig KCONFIG_ALLCONFIG="$KERNELOUTPUT"/.config.test > /dev/null
++
++ # Compare. The date changes, so expect a small difference each time.
++ D=$(diff "$KERNELOUTPUT"/.config .config | wc -l)
++ if [ $D -eq 4 ]
++ then
++ mv "$KERNELOUTPUT"/.config.test "$OUTPUT"
++ LENGTH=$[$LENGTH-1]
++ else
++ I=$[$I + 1]
++ fi
++done
++
++rm -rf "$KERNELOUTPUT"
++
++# One extra echo to preserve status line.
++echo
+diff --git a/usr/Makefile b/usr/Makefile
+index 201f27f..8e1f6ea 100644
+--- a/usr/Makefile
++++ b/usr/Makefile
+@@ -19,6 +19,7 @@ $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
+
+ hostprogs-y := gen_init_cpio
+ initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
++lzma_initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
+ ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+ $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
+ ramfs-args := \
+@@ -36,6 +37,14 @@ endif
+ quiet_cmd_initfs = GEN $@
+ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
+
++ifdef CONFIG_LZMA_INITRAM_FS_SMALLMEM
++quiet_cmd_lzma_initfs = LZRAMFS $@
++ cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) -s $(ramfs-input)
++else
++quiet_cmd_lzma_initfs = LZRAMFS $@
++ cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) $(ramfs-input)
++endif
++
+ targets := initramfs_data.cpio.gz
+ # do not try to update files included in initramfs
+ $(deps_initramfs): ;
+@@ -48,5 +57,9 @@ $(deps_initramfs): klibcdirs
+ # 4) arguments to gen_initramfs.sh changes
+ $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+ $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
++ifdef CONFIG_LZMA_INITRAM_FS
++ $(call if_changed,lzma_initfs)
++else
+ $(call if_changed,initfs)
++endif
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-002-lzma-vmlinuz.01.patch b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-002-lzma-vmlinuz.01.patch
new file mode 100644
index 0000000000..05361ff9d4
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.21.5-002-lzma-vmlinuz.01.patch
@@ -0,0 +1,54 @@
+diff -rdup linux-2.6.21.5.oorig/arch/i386/boot/compressed/Makefile linux-2.6.21.5/arch/i386/boot/compressed/Makefile
+--- linux-2.6.21.5.oorig/arch/i386/boot/compressed/Makefile 2007-07-24 13:08:51.000000000 +0200
++++ linux-2.6.21.5/arch/i386/boot/compressed/Makefile 2007-07-24 14:54:38.000000000 +0200
+@@ -4,7 +4,7 @@
+ # create a compressed vmlinux image from the original vmlinux
+ #
+
+-tragets := head.o lzma_misc.o piggy.o \
++targets := head.o lzma_misc.o piggy.o \
+ vmlinux.bin.all vmlinux.relocs \
+ vmlinux vmlinux.bin vmlinux.bin.gz
+ EXTRA_AFLAGS := -traditional
+diff -rdup linux-2.6.21.5.oorig/scripts/gen_lzma_initramfs_list.sh linux-2.6.21.5/scripts/gen_lzma_initramfs_list.sh
+--- linux-2.6.21.5.oorig/scripts/gen_lzma_initramfs_list.sh 2007-07-24 13:08:51.000000000 +0200
++++ linux-2.6.21.5/scripts/gen_lzma_initramfs_list.sh 2007-07-24 15:12:10.000000000 +0200
+@@ -253,7 +253,7 @@ while [ $# -gt 0 ]; do
+ shift
+ ;;
+ "-s")
+- opt="-d16"
++ #opt="-d16" ? what was that supposed to do?
+ ;;
+ "-d") # display default initramfs list
+ default_list="$arg"
+@@ -286,7 +286,7 @@ if [ ! -z ${output_file} ]; then
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+- lzma e ${cpio_tfile} ${output_file} ${opt}
++ lzma -z ${cpio_tfile} ${opt} -c > ${output_file}
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+ fi
+ exit 0
+--- linux-2.6.21.5.oorig/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 15:24:44.000000000 +0200
++++ linux-2.6.21.5/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 17:09:40.000000000 +0200
+@@ -241,7 +241,6 @@ static int lzma_unzip(uch* output)
+
+ static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
+ {
+- static unsigned int i = 0;
+ static unsigned char val;
+ *bufferSize = 1;
+ val = get_byte();
+--- linux-2.6.21.5.oorig/scripts/Makefile.lib 2007-07-24 15:24:44.000000000 +0200
++++ linux-2.6.21.5/scripts/Makefile.lib 2007-07-24 18:03:57.000000000 +0200
+@@ -165,6 +165,7 @@ cmd_gzip = gzip -f -9 < $< > $@
+ # LZMA
+ #
+ quiet_cmd_lzma = LZMA $@
+-cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++#cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++cmd_lzma = lzma -z $< -c > $@
+
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-001-lzma-vmlinuz.00.patch b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-001-lzma-vmlinuz.00.patch
new file mode 100644
index 0000000000..16f9ef7417
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-001-lzma-vmlinuz.00.patch
@@ -0,0 +1,26856 @@
+diff -rduNp linux-2.6.22.1.oorig/.miniconfig linux-2.6.22.1/.miniconfig
+--- linux-2.6.22.1.oorig/.miniconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/.miniconfig 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,89 @@
++#make allnoconfig KCONFIG_ALLCONFIG=miniconfig
++CONFIG_X86_32=y
++CONFIG_CLOCKSOURCE_WATCHDOG=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_MMU=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_DMI=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_PRINTK=y
++CONFIG_BASE_SMALL=1
++CONFIG_BLOCK=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_X86_GENERIC=y
++CONFIG_X86_L1_CACHE_SHIFT=7
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_X86_WP_WORKS_OK=y
++CONFIG_X86_BSWAP=y
++CONFIG_X86_CMPXCHG64=y
++CONFIG_X86_INTEL_USERCOPY=y
++CONFIG_X86_TSC=y
++CONFIG_PREEMPT_NONE=y
++CONFIG_VM86=y
++CONFIG_HIGHMEM=y
++CONFIG_FLATMEM=y
++CONFIG_MTRR=y
++CONFIG_HZ_250=y
++CONFIG_PHYSICAL_ALIGN=0x100000
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_PM=y
++CONFIG_ACPI=y
++CONFIG_ACPI_SLEEP=y
++CONFIG_ACPI_BLACKLIST_YEAR=0
++CONFIG_ACPI_EC=y
++CONFIG_ACPI_SYSTEM=y
++CONFIG_PCI=y
++CONFIG_PCI_GOANY=y
++CONFIG_PCI_DIRECT=y
++CONFIG_BINFMT_ELF=y
++CONFIG_STANDALONE=y
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=2
++CONFIG_BLK_DEV_IDE=y
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_BLK_DEV_IDECD=y
++CONFIG_IDE_GENERIC=y
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++CONFIG_SERIO=y
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_VGA_CONSOLE=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_EXT2_FS=y
++CONFIG_DNOTIFY=y
++CONFIG_ISO9660_FS=y
++CONFIG_FAT_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_RAMFS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_AUFS=y
++CONFIG_AUFS_FAKE_DM=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_DOUBLEFAULT=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_HAS_IOPORT=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_KTIME_SCALAR=y
+diff -rduNp linux-2.6.22.1.oorig/Makefile linux-2.6.22.1/Makefile
+--- linux-2.6.22.1.oorig/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -188,7 +188,7 @@ CROSS_COMPILE ?=
+ # Architecture as present in compile.h
+ UTS_MACHINE := $(ARCH)
+
+-KCONFIG_CONFIG ?= .config
++KCONFIG_CONFIG ?= .miniconfig
+
+ # SHELL used by kbuild
+ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
+diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.c linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.c
+--- linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,588 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder (optimized for Speed version)
++
++ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this Code, expressly permits you to
++ statically or dynamically link your Code (or bind by name) to the
++ interfaces of this file without subjecting your linked Code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_READ_BYTE (*Buffer++)
++
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
++
++#ifdef _LZMA_IN_CB
++
++#define RC_TEST { if (Buffer == BufferLim) \
++ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
++
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
++
++#else
++
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
++
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
++
++#endif
++
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
++
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
++
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
++ { UpdateBit0(p); mi <<= 1; A0; } else \
++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
++
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
++
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
++ { int i = numLevels; res = 1; \
++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
++ res -= (1 << numLevels); }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
++{
++ unsigned char prop0;
++ if (size < LZMA_PROPERTIES_SIZE)
++ return LZMA_RESULT_DATA_ERROR;
++ prop0 = propsData[0];
++ if (prop0 >= (9 * 5 * 5))
++ return LZMA_RESULT_DATA_ERROR;
++ {
++ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
++ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
++ propsRes->lc = prop0;
++ /*
++ unsigned char remainder = (unsigned char)(prop0 / 9);
++ propsRes->lc = prop0 % 9;
++ propsRes->pb = remainder / 5;
++ propsRes->lp = remainder % 5;
++ */
++ }
++
++ #ifdef _LZMA_OUT_READ
++ {
++ int i;
++ propsRes->DictionarySize = 0;
++ for (i = 0; i < 4; i++)
++ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
++ if (propsRes->DictionarySize == 0)
++ propsRes->DictionarySize = 1;
++ }
++ #endif
++ return LZMA_RESULT_OK;
++}
++
++#define kLzmaStreamWasFinishedId (-1)
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
++{
++ CProb *p = vs->Probs;
++ SizeT nowPos = 0;
++ Byte previousByte = 0;
++ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
++ int lc = vs->Properties.lc;
++
++ #ifdef _LZMA_OUT_READ
++
++ UInt32 Range = vs->Range;
++ UInt32 Code = vs->Code;
++ #ifdef _LZMA_IN_CB
++ const Byte *Buffer = vs->Buffer;
++ const Byte *BufferLim = vs->BufferLim;
++ #else
++ const Byte *Buffer = inStream;
++ const Byte *BufferLim = inStream + inSize;
++ #endif
++ int state = vs->State;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++ UInt32 distanceLimit = vs->DistanceLimit;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->Properties.DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ Byte tempDictionary[4];
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++ if (len == kLzmaStreamWasFinishedId)
++ return LZMA_RESULT_OK;
++
++ if (dictionarySize == 0)
++ {
++ dictionary = tempDictionary;
++ dictionarySize = 1;
++ tempDictionary[0] = vs->TempDictionary[0];
++ }
++
++ if (len == kLzmaNeedInitId)
++ {
++ {
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ UInt32 i;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ rep0 = rep1 = rep2 = rep3 = 1;
++ state = 0;
++ globalPos = 0;
++ distanceLimit = 0;
++ dictionaryPos = 0;
++ dictionary[dictionarySize - 1] = 0;
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++ }
++ len = 0;
++ }
++ while(len != 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++
++ #else /* if !_LZMA_OUT_READ */
++
++ int state = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ int len = 0;
++ const Byte *Buffer;
++ const Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++
++ {
++ UInt32 i;
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ }
++
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++
++ #endif /* _LZMA_OUT_READ */
++
++ while(nowPos < outSize)
++ {
++ CProb *prob;
++ UInt32 bound;
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++
++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ int symbol = 1;
++ UpdateBit0(prob)
++ prob = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state >= kNumLitStates)
++ {
++ int matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ do
++ {
++ int bit;
++ CProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & 0x100);
++ probLit = prob + 0x100 + bit + symbol;
++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
++ }
++ while (symbol < 0x100);
++ }
++ while (symbol < 0x100)
++ {
++ CProb *probLit = prob + symbol;
++ RC_GET_BIT(probLit, symbol)
++ }
++ previousByte = (Byte)symbol;
++
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRep + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < kNumLitStates ? 0 : 3;
++ prob = p + LenCoder;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG0 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ UpdateBit0(prob);
++
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit == 0)
++ #else
++ if (nowPos == 0)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ state = state < kNumLitStates ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++ #endif
++
++ continue;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ UpdateBit1(prob);
++ prob = p + IsRepG1 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep1;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG2 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep2;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ state = state < kNumLitStates ? 8 : 11;
++ prob = p + RepLenCoder;
++ }
++ {
++ int numBits, offset;
++ CProb *probLen = prob + LenChoice;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ numBits = kLenNumLowBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenChoice2;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ numBits = kLenNumMidBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ numBits = kLenNumHighBits;
++ }
++ }
++ RangeDecoderBitTreeDecode(probLen, numBits, len);
++ len += offset;
++ }
++
++ if (state < 4)
++ {
++ int posSlot;
++ state += kNumLitStates;
++ prob = p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits);
++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = (2 | ((UInt32)posSlot & 1));
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 <<= numDirectBits;
++ prob = p + SpecPos + rep0 - posSlot - 1;
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ RC_NORMALIZE
++ Range >>= 1;
++ rep0 <<= 1;
++ if (Code >= Range)
++ {
++ Code -= Range;
++ rep0 |= 1;
++ }
++ }
++ while (--numDirectBits != 0);
++ prob = p + Align;
++ rep0 <<= kNumAlignBits;
++ numDirectBits = kNumAlignBits;
++ }
++ {
++ int i = 1;
++ int mi = 1;
++ do
++ {
++ CProb *prob3 = prob + mi;
++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
++ i <<= 1;
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ else
++ rep0 = posSlot;
++ if (++rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = kLzmaStreamWasFinishedId;
++ break;
++ }
++ }
++
++ len += kMatchMinLen;
++ #ifdef _LZMA_OUT_READ
++ if (rep0 > distanceLimit)
++ #else
++ if (rep0 > nowPos)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ #ifdef _LZMA_OUT_READ
++ if (dictionarySize - distanceLimit > (UInt32)len)
++ distanceLimit += len;
++ else
++ distanceLimit = dictionarySize;
++ #endif
++
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ len--;
++ outStream[nowPos++] = previousByte;
++ }
++ while(len != 0 && nowPos < outSize);
++ }
++ }
++ RC_NORMALIZE;
++
++ #ifdef _LZMA_OUT_READ
++ vs->Range = Range;
++ vs->Code = Code;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + (UInt32)nowPos;
++ vs->DistanceLimit = distanceLimit;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->RemainLen = len;
++ vs->TempDictionary[0] = tempDictionary[0];
++ #endif
++
++ #ifdef _LZMA_IN_CB
++ vs->Buffer = Buffer;
++ vs->BufferLim = BufferLim;
++ #else
++ *inSizeProcessed = (SizeT)(Buffer - inStream);
++ #endif
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.h linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.h
+--- linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,131 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++/* #define _LZMA_SYSTEM_SIZE_T */
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifndef SizeT
++#ifdef _LZMA_SYSTEM_SIZE_T
++#include <stddef.h>
++#define SizeT size_t
++#else
++#define SizeT UInt32
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_PROPERTIES_SIZE 5
++
++typedef struct _CLzmaProperties
++{
++ int lc;
++ int lp;
++ int pb;
++ #ifdef _LZMA_OUT_READ
++ UInt32 DictionarySize;
++ #endif
++}CLzmaProperties;
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
++
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
++
++#define kLzmaNeedInitId (-2)
++
++typedef struct _CLzmaDecoderState
++{
++ CLzmaProperties Properties;
++ CProb *Probs;
++
++ #ifdef _LZMA_IN_CB
++ const unsigned char *Buffer;
++ const unsigned char *BufferLim;
++ #endif
++
++ #ifdef _LZMA_OUT_READ
++ unsigned char *Dictionary;
++ UInt32 Range;
++ UInt32 Code;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 DistanceLimit;
++ UInt32 Reps[4];
++ int State;
++ int RemainLen;
++ unsigned char TempDictionary[4];
++ #endif
++} CLzmaDecoderState;
++
++#ifdef _LZMA_OUT_READ
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
++#endif
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
++
++#endif
+diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/Makefile linux-2.6.22.1/arch/i386/boot/compressed/Makefile
+--- linux-2.6.22.1.oorig/arch/i386/boot/compressed/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/arch/i386/boot/compressed/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -4,15 +4,16 @@
+ # create a compressed vmlinux image from the original vmlinux
+ #
+
+-targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
+- vmlinux.bin.all vmlinux.relocs
++tragets := head.o lzma_misc.o piggy.o \
++ vmlinux.bin.all vmlinux.relocs \
++ vmlinux vmlinux.bin vmlinux.bin.gz
+ EXTRA_AFLAGS := -traditional
+
+ LDFLAGS_vmlinux := -T
+-CFLAGS_misc.o += -fPIC
++CFLAGS_lzma_misc.o += -fPIC
+ hostprogs-y := relocs
+
+-$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
++$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/lzma_misc.o $(obj)/piggy.o FORCE
+ $(call if_changed,ld)
+ @:
+
+@@ -33,10 +34,10 @@ $(obj)/vmlinux.bin.all: $(vmlinux.bin.al
+
+ ifdef CONFIG_RELOCATABLE
+ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
+- $(call if_changed,gzip)
++ $(call if_changed,lzma)
+ else
+ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+- $(call if_changed,gzip)
++ $(call if_changed,lzma)
+ endif
+
+ LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/lzma_misc.c linux-2.6.22.1/arch/i386/boot/compressed/lzma_misc.c
+--- linux-2.6.22.1.oorig/arch/i386/boot/compressed/lzma_misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,290 @@
++/*
++ * lzma_misc.c
++ *
++ * Decompress LZMA compressed vmlinuz
++ * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com
++ * Program adapted from misc.c for 2.6.20.1 kernel
++ * Please refer to misc.c for authorship and copyright.
++ * Date: 25 March 2007
++ * Source released under GPL
++ */
++
++#undef CONFIG_PARAVIRT
++#include <linux/linkage.h>
++#include <linux/vmalloc.h>
++#include <linux/screen_info.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/boot.h>
++
++/* WARNING!!
++ * This code is compiled with -fPIC and it is relocated dynamically
++ * at run time, but no relocation processing is performed.
++ * This means that it is not safe to place pointers in static structures.
++ */
++
++#define OF(args) args
++#define STATIC static
++
++#undef memset
++#undef memcpy
++
++typedef unsigned char uch;
++typedef unsigned short ush;
++typedef unsigned long ulg;
++
++#define WSIZE 0x80000000 /* Window size must be at least 32k,
++ * and a power of two
++ * We don't actually have a window just
++ * a huge output buffer so I report
++ * a 2G windows size, as that should
++ * always be larger than our output buffer.
++ */
++
++static uch *inbuf; /* input buffer */
++static uch *window; /* Sliding window buffer, (and final output buffer) */
++
++static unsigned insize; /* valid bytes in inbuf */
++static unsigned inptr; /* index of next byte to be processed in inbuf */
++
++/* 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 */
++
++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
++
++/* Diagnostic functions */
++#ifdef DEBUG
++# define Assert(cond,msg) {if(!(cond)) error(msg);}
++# define Trace(x) fprintf x
++# define Tracev(x) {if (verbose) fprintf x ;}
++# define Tracevv(x) {if (verbose>1) fprintf x ;}
++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#else
++# define Assert(cond,msg)
++# define Trace(x)
++# define Tracev(x)
++# define Tracevv(x)
++# define Tracec(c,x)
++# define Tracecv(c,x)
++#endif
++
++static int fill_inbuf(void);
++static void error(char *m);
++
++/*
++ * This is set up by the setup-routine at boot-time
++ */
++static unsigned char *real_mode; /* Pointer to real-mode data */
++
++#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
++#ifndef STANDARD_MEMORY_BIOS_CALL
++#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
++#endif
++#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
++
++extern unsigned char input_data[];
++extern int input_len;
++
++static long bytes_out = 0;
++
++static void *memcpy(void *dest, const void *src, unsigned n);
++
++static void putstr(const char *);
++
++static unsigned long free_mem_ptr;
++static unsigned long free_mem_end_ptr;
++
++#define HEAP_SIZE 0x3000
++
++static char *vidmem = (char *)0xb8000;
++static int vidport;
++static int lines, cols;
++
++#ifdef CONFIG_X86_NUMAQ
++void *xquad_portio;
++#endif
++
++static void scroll(void)
++{
++ int i;
++
++ memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
++ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
++ vidmem[i] = ' ';
++}
++
++static void putstr(const char *s)
++{
++ int x,y,pos;
++ char c;
++
++ x = RM_SCREEN_INFO.orig_x;
++ y = RM_SCREEN_INFO.orig_y;
++
++ while ( ( c = *s++ ) != '\0' ) {
++ if ( c == '\n' ) {
++ x = 0;
++ if ( ++y >= lines ) {
++ scroll();
++ y--;
++ }
++ } else {
++ vidmem [ ( x + cols * y ) * 2 ] = c;
++ if ( ++x >= cols ) {
++ x = 0;
++ if ( ++y >= lines ) {
++ scroll();
++ y--;
++ }
++ }
++ }
++ }
++
++ RM_SCREEN_INFO.orig_x = x;
++ RM_SCREEN_INFO.orig_y = y;
++
++ pos = (x + cols * y) * 2; /* Update cursor position */
++ outb_p(14, vidport);
++ outb_p(0xff & (pos >> 9), vidport+1);
++ outb_p(15, vidport);
++ outb_p(0xff & (pos >> 1), vidport+1);
++}
++
++static void* memcpy(void* dest, const void* src, unsigned n)
++{
++ int i;
++ char *d = (char *)dest, *s = (char *)src;
++
++ for (i=0;i<n;i++) d[i] = s[i];
++ return dest;
++}
++
++/* ===========================================================================
++ * Fill the input buffer. This is called only when the buffer is empty
++ * and at least one byte is really needed.
++ */
++static int fill_inbuf(void)
++{
++ error("ran out of input data");
++ return 0;
++}
++
++/* ===========================================================================
++ */
++static void error(char *x)
++{
++ putstr("\n\n");
++ putstr(x);
++ putstr("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++#define _LZMA_IN_CB
++#include "LzmaDecode.h"
++#include "LzmaDecode.c"
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
++
++/*
++ * Do the lzma decompression
++ */
++static int lzma_unzip(uch* output)
++{
++
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++
++ ILzmaInCallback callback;
++ callback.Read = read_byte;
++
++ // lzma args
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ // skip dictionary size
++ for (i = 0; i < 4; i++)
++ get_byte();
++ // get uncompressed size
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // skip high order bytes
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ // Just point it beyond
++ state.Probs = (CProb*) ( free_mem_ptr );
++ // decompress kernel
++ if (LzmaDecode( &state, &callback,
++ (unsigned char*)output, uncompressedSize, &i) == LZMA_RESULT_OK)
++ {
++ if ( i != uncompressedSize )
++ error( "kernel corrupted!\n");
++ bytes_out = i;
++ return 0;
++ }
++ return 1;
++}
++
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned int i = 0;
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++asmlinkage void decompress_kernel(void *rmode, unsigned long end,
++ uch *input_data, unsigned long input_len, uch *output)
++{
++ real_mode = rmode;
++
++ if (RM_SCREEN_INFO.orig_video_mode == 7) {
++ vidmem = (char *) 0xb0000;
++ vidport = 0x3b4;
++ } else {
++ vidmem = (char *) 0xb8000;
++ vidport = 0x3d4;
++ }
++
++ lines = RM_SCREEN_INFO.orig_video_lines;
++ cols = RM_SCREEN_INFO.orig_video_cols;
++
++ window = output; /* Output buffer (Normally at 1M) */
++ free_mem_ptr = end; /* Heap */
++ free_mem_end_ptr = end + HEAP_SIZE;
++ inbuf = input_data; /* Input buffer */
++ insize = input_len;
++ inptr = 0;
++
++ if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
++ error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
++ if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
++ error("Destination address too large");
++#ifndef CONFIG_RELOCATABLE
++ if ((u32)output != LOAD_PHYSICAL_ADDR)
++ error("Wrong destination address");
++#endif
++ if( lzma_unzip(output) != 0 )
++ {
++ error("inflate error\n");
++ }
++ putstr("Ok, booting the kernel.\n");
++
++ return;
++}
+diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/vmlinux.scr linux-2.6.22.1/arch/i386/boot/compressed/vmlinux.scr
+--- linux-2.6.22.1.oorig/arch/i386/boot/compressed/vmlinux.scr 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/arch/i386/boot/compressed/vmlinux.scr 2007-07-24 14:17:46.000000000 +0200
+@@ -3,8 +3,8 @@ SECTIONS
+ .data.compressed : {
+ input_len = .;
+ LONG(input_data_end - input_data) input_data = .;
++ output_len = . + 5;
+ *(.data)
+- output_len = . - 4;
+ input_data_end = .;
+ }
+ }
+diff -rduNp linux-2.6.22.1.oorig/drivers/block/Kconfig linux-2.6.22.1/drivers/block/Kconfig
+--- linux-2.6.22.1.oorig/drivers/block/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/drivers/block/Kconfig 2007-07-24 14:17:46.000000000 +0200
+@@ -406,6 +406,47 @@ config BLK_DEV_RAM_BLOCKSIZE
+ setups function - apparently needed by the rd_load_image routine
+ that supposes the filesystem in the image uses a 1024 blocksize.
+
++config LZMA_INITRD
++ boolean "Allow LZMA compression on initrd"
++ depends on BLK_DEV_INITRD=y
++ default "y"
++ help
++ Use lzma compression on initrd, example 'lzma e initrd initrd.7z -d16'.
++ If you have sufficient memory, you could compress using bigger dictionary size,
++ 'lzma e initrd initrd.7z'.
++
++config LZMA_INITRD_KMALLOC_ONLY
++ boolean "Use only kmalloc, do not use vmalloc on lzma initrd"
++ depends on LZMA_INITRD=y
++ default "n"
++ help
++ Set to y if you do not want to use vmalloc, ie use only kmalloc.
++
++config LZMA_INITRAM_FS
++ boolean "Allow LZMA compression on initramfs"
++ depends on BLK_DEV_RAM=y
++ default "y"
++ help
++ Use lzma compression on initramfs, example 'lzma e initramfs.cpio initramfs.cpio.lzma'.
++
++config LZMA_INITRAM_FS_SMALLMEM
++ boolean "Use lzma compression with small dictonary size."
++ depends on LZMA_INITRAM_FS=y
++ default "y"
++ help
++ Use lzma compression on initramfs with small dictionary size, example
++ 'lzma e initramfs.cpio initramfs.cpio.lzma -d16'.
++ Affects only the initramfs.cpio in the ~usr directory, which is compiled into
++ the kernel. If you prepared initramfs.cpio for use with bootloader, you would
++ need to specify the commandline options (-d16) yourself.
++
++config LZMA_INITRAM_FS_KMALLOC_ONLY
++ boolean "Use only kmalloc, do not use vmalloc on lzma initramfs"
++ depends on LZMA_INITRAM_FS=y
++ default "n"
++ help
++ Set to y if you do not want to use vmalloc, ie use only kmalloc.
++
+ config CDROM_PKTCDVD
+ tristate "Packet writing on CD/DVD media"
+ depends on !UML
+diff -rduNp linux-2.6.22.1.oorig/fs/Kconfig linux-2.6.22.1/fs/Kconfig
+--- linux-2.6.22.1.oorig/fs/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/fs/Kconfig 2007-07-24 14:17:46.000000000 +0200
+@@ -1367,6 +1367,71 @@ config CRAMFS
+
+ If unsure, say N.
+
++config SQUASHFS
++ tristate "SquashFS 3.2 - Squashed file system support"
++ select ZLIB_INFLATE
++ help
++ Saying Y here includes support for SquashFS 3.2 (a Compressed Read-Only File
++ System). Squashfs is a highly compressed read-only filesystem for Linux.
++ It uses zlib compression to compress both files, inodes and directories.
++ Inodes in the system are very small and all blocks are packed to minimise
++ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
++ SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full
++ uid/gid information, hard links and timestamps.
++
++ Squashfs is intended for general read-only filesystem use, for archival
++ use (i.e. in cases where a .tar.gz file may be used), and in embedded
++ systems where low overhead is needed. Further information and filesystem tools
++ are available from http://squashfs.sourceforge.net.
++
++ If you want to compile this as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called squashfs. Note that the root file system (the one
++ containing the directory /) cannot be compiled as a module.
++
++ If unsure, say N.
++
++config SQUASHFS_EMBEDDED
++
++ bool "Additional options for memory-constrained systems"
++ depends on SQUASHFS
++ default n
++ help
++ Saying Y here allows you to specify cache sizes and how Squashfs
++ allocates memory. This is only intended for memory constrained
++ systems.
++
++ If unsure, say N.
++
++config SQUASHFS_FRAGMENT_CACHE_SIZE
++ int "Number of fragments cached" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default "3"
++ help
++ By default SquashFS caches the last 3 fragments read from
++ the filesystem. Increasing this amount may mean SquashFS
++ has to re-read fragments less often from disk, at the expense
++ of extra system memory. Decreasing this amount will mean
++ SquashFS uses less memory at the expense of extra reads from disk.
++
++ Note there must be at least one cached fragment. Anything
++ much more than three will probably not make much difference.
++
++config SQUASHFS_VMALLOC
++ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
++ depends on SQUASHFS
++ default n
++ help
++ By default SquashFS uses kmalloc to obtain fragment cache memory.
++ Kmalloc memory is the standard kernel allocator, but it can fail
++ on memory constrained systems. Because of the way Vmalloc works,
++ Vmalloc can succeed when kmalloc fails. Specifying this option
++ will make SquashFS always use Vmalloc to allocate the
++ fragment cache memory.
++
++ If unsure, say N.
++
+ config VXFS_FS
+ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+ depends on BLOCK
+@@ -2072,3 +2137,4 @@ source "fs/dlm/Kconfig"
+
+ endmenu
+
++source "fs/aufs/Kconfig"
+diff -rduNp linux-2.6.22.1.oorig/fs/Makefile linux-2.6.22.1/fs/Makefile
+--- linux-2.6.22.1.oorig/fs/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/fs/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/
+ obj-$(CONFIG_JBD2) += jbd2/
+ obj-$(CONFIG_EXT2_FS) += ext2/
+ obj-$(CONFIG_CRAMFS) += cramfs/
++obj-$(CONFIG_SQUASHFS) += squashfs/
+ obj-$(CONFIG_RAMFS) += ramfs/
+ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
+ obj-$(CONFIG_CODA_FS) += coda/
+@@ -118,3 +119,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
+ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_AUFS) += aufs/
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/Kconfig linux-2.6.22.1/fs/aufs/Kconfig
+--- linux-2.6.22.1.oorig/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/Kconfig 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,73 @@
++config AUFS
++ tristate "Another unionfs"
++ help
++ Aufs is a stackable unification filesystem such as Unionfs,
++ which unifies several directories and provides a merged single
++ directory.
++ In the early days, aufs was entirely re-designed and
++ re-implemented Unionfs Version 1.x series. After many original
++ ideas, approaches and improvements, it becomes totally
++ different from Unionfs while keeping the basic features.
++ See Unionfs for the basic features.
++
++if AUFS
++comment "These options are generated automatically for "#UTS_RELEASE
++
++config AUFS_FAKE_DM
++ bool "Use simplified (fake) nameidata"
++ depends on AUFS
++ default y
++ help
++ Faking nameidata (VFS internal data), you can get better performance
++ in some cases.
++
++choice
++ prompt "Maximum number of branches"
++ depends on AUFS
++ default AUFS_BRANCH_MAX_127
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_127
++ bool "127"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_511
++ bool "511"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++config AUFS_BRANCH_MAX_1023
++ bool "1023"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++
++config AUFS_BRANCH_MAX_32767
++ bool "32767"
++ help
++ Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
++endchoice
++config AUFS_DEBUG
++ bool "Debug aufs"
++ depends on AUFS
++ default y
++ help
++ Enable this to compile aufs internal debug code.
++ The performance will be damaged.
++
++config AUFS_COMPAT
++ bool "Compatibility with Unionfs (obsolete)"
++ depends on AUFS
++ default n
++ help
++ This makes aufs compatible with unionfs-style mount options and some
++ behaviours.
++ The dirs= mount option and =nfsro branch permission flag are always
++ interpreted as br: mount option and =ro flag respectively. The
++ 'debug', 'delete' and 'imap' mount options are ignored.
++ If you disable this option, you will get,
++ - aufs issues a warning about the ignored mount options
++ - the default branch permission flag is set. RW for the first branch,
++ and RO for the rests.
++ - the name of a internal file which represents the directory is
++ 'opaque', becomes '.wh..wh..opq'
++ - the 'diropq=w' mount option is set by default
++endif
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/Makefile linux-2.6.22.1/fs/aufs/Makefile
+--- linux-2.6.22.1.oorig/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,18 @@
++# AUFS Makefile for the Linux 2.6.16 and later
++# $Id: Makefile,v 1.29 2007/04/23 00:59:50 sfjro Exp $
++
++obj-$(CONFIG_AUFS) += aufs.o
++aufs-y := module.o super.o sbinfo.o xino.o \
++ branch.o cpup.o whout.o plink.o wkq.o dcsub.o vfsub.o \
++ opts.o \
++ dentry.o dinfo.o \
++ file.o f_op.o finfo.o \
++ dir.o vdir.o \
++ inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
++ misc.o
++#xattr.o
++aufs-$(CONFIG_AUFS_SYSAUFS) += sysaufs.o
++aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
++aufs-$(CONFIG_AUFS_EXPORT) += export.o
++#aufs-$(CONFIG_DEBUGFS) += dbgfs.o
++aufs-$(CONFIG_AUFS_DEBUG) += debug.o
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/aufs.h linux-2.6.22.1/fs/aufs/aufs.h
+--- linux-2.6.22.1.oorig/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/aufs.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: aufs.h,v 1.24 2007/05/14 03:41:51 sfjro Exp $ */
++
++#ifndef __AUFS_H__
++#define __AUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/version.h>
++
++/* limited support before 2.6.16, curretly 2.6.15 only. */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++#define atomic_long_t atomic_t
++#define atomic_long_set atomic_set
++#define timespec_to_ns(ts) ({(long long)(ts)->tv_sec;})
++#define D_CHILD d_child
++#else
++#define D_CHILD d_u.d_child
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++#include "debug.h"
++
++#include "branch.h"
++#include "cpup.h"
++#include "dcsub.h"
++#include "dentry.h"
++#include "dir.h"
++#include "file.h"
++#include "inode.h"
++#include "misc.h"
++#include "module.h"
++#include "opts.h"
++#include "super.h"
++#include "sysaufs.h"
++#include "vfsub.h"
++#include "whout.h"
++#include "wkq.h"
++//#include "xattr.h"
++
++#if defined(CONFIG_AUFS_MODULE) && !defined(CONFIG_AUFS_KSIZE_PATCH)
++#define ksize(p) (-1U)
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/branch.c linux-2.6.22.1/fs/aufs/branch.c
+--- linux-2.6.22.1.oorig/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/branch.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,818 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: branch.c,v 1.49 2007/05/14 03:38:23 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++static void free_branch(struct aufs_branch *br)
++{
++ TraceEnter();
++
++ if (br->br_xino)
++ fput(br->br_xino);
++ dput(br->br_wh);
++ dput(br->br_plink);
++ mntput(br->br_mnt);
++ DEBUG_ON(br_count(br) || atomic_read(&br->br_wh_running));
++ kfree(br);
++}
++
++/*
++ * frees all branches
++ */
++void free_branches(struct aufs_sbinfo *sbinfo)
++{
++ aufs_bindex_t bmax;
++ struct aufs_branch **br;
++
++ TraceEnter();
++ bmax = sbinfo->si_bend + 1;
++ br = sbinfo->si_branch;
++ while (bmax--)
++ free_branch(*br++);
++}
++
++/*
++ * find the index of a branch which is specified by @br_id.
++ */
++int find_brindex(struct super_block *sb, aufs_bindex_t br_id)
++{
++ aufs_bindex_t bindex, bend;
++
++ TraceEnter();
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (sbr_id(sb, bindex) == br_id)
++ return bindex;
++ return -1;
++}
++
++/*
++ * test if the @br is readonly or not.
++ */
++int br_rdonly(struct aufs_branch *br)
++{
++ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
++ || !br_writable(br->br_perm))
++ ? -EROFS : 0;
++}
++
++/*
++ * returns writable branch index, otherwise an error.
++ * todo: customizable writable-branch-policy
++ */
++static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
++{
++ int err;
++ aufs_bindex_t bindex, candidate;
++ struct super_block *sb;
++ struct dentry *parent, *hidden_parent;
++
++ err = bend;
++ sb = dentry->d_sb;
++ parent = dget_parent(dentry);
++#if 1 // branch policy
++ hidden_parent = au_h_dptr_i(parent, bend);
++ if (hidden_parent && !br_rdonly(stobr(sb, bend)))
++ goto out; /* success */
++#endif
++
++ candidate = -1;
++ for (bindex = dbstart(parent); bindex <= bend; bindex++) {
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ if (hidden_parent && !br_rdonly(stobr(sb, bindex))) {
++#if 0 // branch policy
++ if (candidate == -1)
++ candidate = bindex;
++ if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
++ return bindex;
++#endif
++ err = bindex;
++ goto out; /* success */
++ }
++ }
++#if 0 // branch policy
++ err = candidate;
++ if (candidate != -1)
++ goto out; /* success */
++#endif
++ err = -EROFS;
++
++ out:
++ dput(parent);
++ return err;
++}
++
++int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++
++ for (bindex = bend; bindex >= 0; bindex--)
++ if (!br_rdonly(stobr(sb, bindex)))
++ return bindex;
++ return -EROFS;
++}
++
++int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
++{
++ int err;
++
++ err = find_rw_parent(dentry, bend);
++ if (err >= 0)
++ return err;
++ return find_rw_br(dentry->d_sb, bend);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if two hidden_dentries have overlapping branches.
++ */
++//todo: try is_subdir()
++static int do_is_overlap(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ struct dentry *d;
++
++ d = hidden_d1;
++ do {
++ if (unlikely(d == hidden_d2))
++ return 1;
++ d = d->d_parent; // dget_parent()
++ } while (!IS_ROOT(d));
++
++ return (d == hidden_d2);
++}
++
++#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
++#include <linux/loop.h>
++static int is_overlap_loopback(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ struct inode *hidden_inode;
++ struct loop_device *l;
++
++ hidden_inode = hidden_d1->d_inode;
++ if (MAJOR(hidden_inode->i_sb->s_dev) != LOOP_MAJOR)
++ return 0;
++
++ l = hidden_inode->i_sb->s_bdev->bd_disk->private_data;
++ hidden_d1 = l->lo_backing_file->f_dentry;
++ if (unlikely(hidden_d1->d_sb == sb))
++ return 1;
++ return do_is_overlap(sb, hidden_d1, hidden_d2);
++}
++#else
++#define is_overlap_loopback(sb, hidden_d1, hidden_d2) 0
++#endif
++
++static int is_overlap(struct super_block *sb, struct dentry *hidden_d1,
++ struct dentry *hidden_d2)
++{
++ LKTRTrace("d1 %.*s, d2 %.*s\n", DLNPair(hidden_d1), DLNPair(hidden_d2));
++ if (unlikely(hidden_d1 == hidden_d2))
++ return 1;
++ return do_is_overlap(sb, hidden_d1, hidden_d2)
++ || do_is_overlap(sb, hidden_d2, hidden_d1)
++ || is_overlap_loopback(sb, hidden_d1, hidden_d2)
++ || is_overlap_loopback(sb, hidden_d2, hidden_d1);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int init_br_wh(struct super_block *sb, aufs_bindex_t bindex,
++ struct aufs_branch *br, int new_perm,
++ struct dentry *h_root, struct vfsmount *h_mnt)
++{
++ int err, old_perm;
++ struct inode *dir = sb->s_root->d_inode,
++ *h_dir = h_root->d_inode;
++ const int new = (bindex < 0);
++
++ LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
++
++ if (new)
++ hi_lock_parent(h_dir);
++ else
++ hdir_lock(h_dir, dir, bindex);
++
++ br_wh_write_lock(br);
++ old_perm = br->br_perm;
++ br->br_perm = new_perm;
++ err = init_wh(h_root, br, au_do_nfsmnt(h_mnt), sb);
++ br->br_perm = old_perm;
++ br_wh_write_unlock(br);
++
++ if (new)
++ i_unlock(h_dir);
++ else
++ hdir_unlock(h_dir, dir, bindex);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * returns a newly allocated branch. @new_nbranch is a number of branches
++ * after adding a branch.
++ */
++static struct aufs_branch *alloc_addbr(struct super_block *sb, int new_nbranch)
++{
++ struct aufs_branch **branchp, *add_branch;
++ int sz;
++ void *p;
++ struct dentry *root;
++ struct inode *inode;
++ struct aufs_hinode *hinodep;
++ struct aufs_hdentry *hdentryp;
++
++ LKTRTrace("new_nbranch %d\n", new_nbranch);
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ IiMustWriteLock(inode);
++
++ add_branch = kmalloc(sizeof(*add_branch), GFP_KERNEL);
++ //if (LktrCond) {kfree(add_branch); add_branch = NULL;}
++ if (unlikely(!add_branch))
++ goto out;
++
++ sz = sizeof(*branchp) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*branchp);
++ p = stosi(sb)->si_branch;
++ branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) branchp = NULL;
++ if (unlikely(!branchp))
++ goto out;
++ stosi(sb)->si_branch = branchp;
++
++ sz = sizeof(*hdentryp) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*hdentryp);
++ p = dtodi(root)->di_hdentry;
++ hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) hdentryp = NULL;
++ if (unlikely(!hdentryp))
++ goto out;
++ dtodi(root)->di_hdentry = hdentryp;
++
++ sz = sizeof(*hinodep) * (new_nbranch - 1);
++ if (unlikely(!sz))
++ sz = sizeof(*hinodep);
++ p = itoii(inode)->ii_hinode;
++ hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch,
++ GFP_KERNEL);
++ //if (LktrCond) hinodep = NULL; // unavailable test
++ if (unlikely(!hinodep))
++ goto out;
++ itoii(inode)->ii_hinode = hinodep;
++ return add_branch; /* success */
++
++ out:
++ kfree(add_branch);
++ TraceErr(-ENOMEM);
++ return ERR_PTR(-ENOMEM);
++}
++
++/*
++ * test if the branch permission is legal or not.
++ */
++static int test_br(struct super_block *sb, struct inode *inode, int brperm,
++ char *path)
++{
++ int err;
++
++ err = 0;
++ if (unlikely(br_writable(brperm) && IS_RDONLY(inode))) {
++ Err("write permission for readonly fs or inode, %s\n", path);
++ err = -EINVAL;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * retunrs,,,
++ * 0: success, the caller will add it
++ * plus: success, it is already unified, the caller should ignore it
++ * minus: error
++ */
++static int test_add(struct super_block *sb, struct opt_add *add, int remount)
++{
++ int err;
++ struct dentry *root;
++ struct inode *inode, *hidden_inode;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%s, remo%d\n", add->path, remount);
++
++ root = sb->s_root;
++ if (unlikely(au_find_dbindex(root, add->nd.dentry) != -1)) {
++ err = 1;
++ if (!remount) {
++ err = -EINVAL;
++ Err("%s duplicated\n", add->path);
++ }
++ goto out;
++ }
++
++ err = -ENOSPC; //-E2BIG;
++ bend = sbend(sb);
++ //if (LktrCond) bend = AUFS_BRANCH_MAX;
++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
++ || AUFS_BRANCH_MAX - 1 <= bend)) {
++ Err("number of branches exceeded %s\n", add->path);
++ goto out;
++ }
++
++ err = -EDOM;
++ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
++ Err("bad index %d\n", add->bindex);
++ goto out;
++ }
++
++ inode = add->nd.dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink)) {
++ Err("no existence %s\n", add->path);
++ goto out;
++ }
++
++ err = -EINVAL;
++ if (unlikely(inode->i_sb == sb)) {
++ Err("%s must be outside\n", add->path);
++ goto out;
++ }
++
++#if 1 //ndef CONFIG_AUFS_ROBR
++ if (unlikely(au_is_aufs(inode->i_sb)
++ || !strcmp(au_sbtype(inode->i_sb), "unionfs"))) {
++ Err("nested " AUFS_NAME " %s\n", add->path);
++ goto out;
++ }
++#endif
++
++#ifdef AuNoNfsBranch
++ if (unlikely(au_is_nfs(inode->i_sb))) {
++ Err(AuNoNfsBranchMsg ". %s\n", add->path);
++ goto out;
++ }
++#endif
++
++ err = test_br(sb, add->nd.dentry->d_inode, add->perm, add->path);
++ if (unlikely(err))
++ goto out;
++
++ if (unlikely(bend == -1))
++ return 0; /* success */
++
++ hidden_inode = au_h_dptr(root)->d_inode;
++ if (unlikely(au_flag_test(sb, AuFlag_WARN_PERM)
++ && ((hidden_inode->i_mode & S_IALLUGO)
++ != (inode->i_mode & S_IALLUGO)
++ || hidden_inode->i_uid != inode->i_uid
++ || hidden_inode->i_gid != inode->i_gid)))
++ Warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++ add->path,
++ inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
++ hidden_inode->i_uid, hidden_inode->i_gid,
++ (hidden_inode->i_mode & S_IALLUGO));
++
++ err = -EINVAL;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(is_overlap(sb, add->nd.dentry,
++ au_h_dptr_i(root, bindex)))) {
++ Err("%s is overlapped\n", add->path);
++ goto out;
++ }
++ err = 0;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int br_add(struct super_block *sb, struct opt_add *add, int remount)
++{
++ int err, sz;
++ aufs_bindex_t bend, add_bindex;
++ struct dentry *root;
++ struct aufs_iinfo *iinfo;
++ struct aufs_sbinfo *sbinfo;
++ struct aufs_dinfo *dinfo;
++ struct inode *root_inode;
++ unsigned long long maxb;
++ struct aufs_branch **branchp, *add_branch;
++ struct aufs_hdentry *hdentryp;
++ struct aufs_hinode *hinodep;
++
++ LKTRTrace("b%d, %s, 0x%x, %.*s\n", add->bindex, add->path,
++ add->perm, DLNPair(add->nd.dentry));
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ root_inode = root->d_inode;
++ IMustLock(root_inode);
++ IiMustWriteLock(root_inode);
++
++ err = test_add(sb, add, remount);
++ if (unlikely(err < 0))
++ goto out;
++ if (unlikely(err))
++ return 0; /* success */
++
++ bend = sbend(sb);
++ add_branch = alloc_addbr(sb, bend + 2);
++ err = PTR_ERR(add_branch);
++ if (IS_ERR(add_branch))
++ goto out;
++
++ err = 0;
++ rw_init_nolock(&add_branch->br_wh_rwsem);
++ add_branch->br_wh = add_branch->br_plink = NULL;
++ if (unlikely(br_writable(add->perm))) {
++ err = init_br_wh(sb, /*bindex*/-1, add_branch, add->perm,
++ add->nd.dentry, add->nd.mnt);
++ if (unlikely(err)) {
++ kfree(add_branch);
++ goto out;
++ }
++ }
++ add_branch->br_xino = NULL;
++ add_branch->br_mnt = mntget(add->nd.mnt);
++ atomic_set(&add_branch->br_wh_running, 0);
++ add_branch->br_id = new_br_id(sb);
++ add_branch->br_perm = add->perm;
++ atomic_set(&add_branch->br_count, 0);
++
++ sbinfo = stosi(sb);
++ dinfo = dtodi(root);
++ iinfo = itoii(root_inode);
++
++ add_bindex = add->bindex;
++ sz = sizeof(*(sbinfo->si_branch)) * (bend + 1 - add_bindex);
++ branchp = sbinfo->si_branch + add_bindex;
++ memmove(branchp + 1, branchp, sz);
++ *branchp = add_branch;
++ sz = sizeof(*hdentryp) * (bend + 1 - add_bindex);
++ hdentryp = dinfo->di_hdentry + add_bindex;
++ memmove(hdentryp + 1, hdentryp, sz);
++ hdentryp->hd_dentry = NULL;
++ sz = sizeof(*hinodep) * (bend + 1 - add_bindex);
++ hinodep = iinfo->ii_hinode + add_bindex;
++ memmove(hinodep + 1, hinodep, sz);
++ hinodep->hi_inode = NULL;
++ hinodep->hi_notify = NULL;
++
++ sbinfo->si_bend++;
++ dinfo->di_bend++;
++ iinfo->ii_bend++;
++ if (unlikely(bend == -1)) {
++ dinfo->di_bstart = 0;
++ iinfo->ii_bstart = 0;
++ }
++ set_h_dptr(root, add_bindex, dget(add->nd.dentry));
++ set_h_iptr(root_inode, add_bindex, igrab(add->nd.dentry->d_inode), 0);
++ if (!add_bindex)
++ au_cpup_attr_all(root_inode);
++ else
++ au_add_nlink(root_inode, add->nd.dentry->d_inode);
++ maxb = add->nd.dentry->d_sb->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++
++ if (au_flag_test(sb, AuFlag_XINO)) {
++ struct file *base_file = stobr(sb, 0)->br_xino;
++ if (!add_bindex)
++ base_file = stobr(sb, 1)->br_xino;
++ err = xino_init(sb, add_bindex, base_file, /*do_test*/1);
++ if (unlikely(err)) {
++ DEBUG_ON(add_branch->br_xino);
++ Err("ignored xino err %d, force noxino\n", err);
++ err = 0;
++ au_flag_clr(sb, AuFlag_XINO);
++ }
++ }
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the branch is deletable or not.
++ */
++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
++{
++ int err, i, j, sigen;
++ struct au_dcsub_pages dpages;
++
++ LKTRTrace("b%d\n", bindex);
++ SiMustWriteLock(root->d_sb);
++ DiMustWriteLock(root);
++
++ err = au_dpages_init(&dpages, GFP_KERNEL);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ sigen = au_sigen(root->d_sb);
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ struct au_dpage *dpage;
++ dpage = dpages.dpages + i;
++ for (j = 0; !err && j < dpage->ndentry; j++) {
++ struct dentry *d;
++
++ d = dpage->dentries[j];
++ if (au_digen(d) == sigen)
++ di_read_lock_child(d, AUFS_I_RLOCK);
++ else {
++ di_write_lock_child(d);
++ err = au_reval_dpath(d, sigen);
++ if (!err)
++ di_downgrade_lock(d, AUFS_I_RLOCK);
++ else {
++ di_write_unlock(d);
++ break;
++ }
++ }
++
++ if (au_h_dptr_i(d, bindex)
++ && (!S_ISDIR(d->d_inode->i_mode)
++ || dbstart(d) == dbend(d)))
++ err = -EBUSY;
++ di_read_unlock(d, AUFS_I_RLOCK);
++ if (err)
++ LKTRTrace("%.*s\n", DLNPair(d));
++ }
++ }
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int br_del(struct super_block *sb, struct opt_del *del, int remount)
++{
++ int err, do_wh, rerr;
++ struct dentry *root;
++ struct inode *inode, *hidden_dir;
++ aufs_bindex_t bindex, bend, br_id;
++ struct aufs_sbinfo *sbinfo;
++ struct aufs_dinfo *dinfo;
++ struct aufs_iinfo *iinfo;
++ struct aufs_branch *br;
++
++ LKTRTrace("%s, %.*s\n", del->path, DLNPair(del->h_root));
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ IiMustWriteLock(inode);
++
++ bindex = au_find_dbindex(root, del->h_root);
++ if (unlikely(bindex < 0)) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ Err("%s no such branch\n", del->path);
++ goto out;
++ }
++ LKTRTrace("bindex b%d\n", bindex);
++
++ err = -EBUSY;
++ bend = sbend(sb);
++ br = stobr(sb, bindex);
++ if (unlikely(!bend || br_count(br))) {
++ LKTRTrace("bend %d, br_count %d\n", bend, br_count(br));
++ goto out;
++ }
++
++ do_wh = 0;
++ hidden_dir = del->h_root->d_inode;
++ if (unlikely(br->br_wh || br->br_plink)) {
++#if 0
++ /* remove whiteout base */
++ err = init_br_wh(sb, bindex, br, AuBr_RO, del->h_root,
++ br->br_mnt);
++ if (unlikely(err))
++ goto out;
++#else
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++#endif
++ do_wh = 1;
++ }
++
++ err = test_children_busy(root, bindex);
++ if (unlikely(err)) {
++ if (unlikely(do_wh))
++ goto out_wh;
++ goto out;
++ }
++
++ err = 0;
++ sbinfo = stosi(sb);
++ dinfo = dtodi(root);
++ iinfo = itoii(inode);
++
++ dput(au_h_dptr_i(root, bindex));
++ aufs_hiput(iinfo->ii_hinode + bindex);
++ br_id = br->br_id;
++ free_branch(br);
++
++ //todo: realloc and shrink memeory
++ if (bindex < bend) {
++ const aufs_bindex_t n = bend - bindex;
++ struct aufs_branch **brp;
++ struct aufs_hdentry *hdp;
++ struct aufs_hinode *hip;
++
++ brp = sbinfo->si_branch + bindex;
++ memmove(brp, brp + 1, sizeof(*brp) * n);
++ hdp = dinfo->di_hdentry + bindex;
++ memmove(hdp, hdp + 1, sizeof(*hdp) * n);
++ hip = iinfo->ii_hinode + bindex;
++ memmove(hip, hip + 1, sizeof(*hip) * n);
++ }
++ sbinfo->si_branch[0 + bend] = NULL;
++ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
++ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
++ iinfo->ii_hinode[0 + bend].hi_notify = NULL;
++
++ sbinfo->si_bend--;
++ dinfo->di_bend--;
++ iinfo->ii_bend--;
++ if (!bindex)
++ au_cpup_attr_all(inode);
++ else
++ au_sub_nlink(inode, del->h_root->d_inode);
++ if (au_flag_test(sb, AuFlag_PLINK))
++ half_refresh_plink(sb, br_id);
++
++ if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
++ bend--;
++ sb->s_maxbytes = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ unsigned long long maxb;
++ maxb = sbr_sb(sb, bindex)->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++ }
++ }
++ goto out; /* success */
++
++ out_wh:
++ /* revert */
++ rerr = init_br_wh(sb, bindex, br, br->br_perm, del->h_root, br->br_mnt);
++ if (rerr)
++ Warn("failed re-creating base whiteout, %s. (%d)\n",
++ del->path, rerr);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int do_need_sigen_inc(int a, int b)
++{
++ return (br_whable(a) && !br_whable(b));
++}
++
++static int need_sigen_inc(int old, int new)
++{
++ return (do_need_sigen_inc(old, new)
++ || do_need_sigen_inc(new, old));
++}
++
++int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
++ int *do_update)
++{
++ int err;
++ struct dentry *root;
++ aufs_bindex_t bindex;
++ struct aufs_branch *br;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%s, %.*s, 0x%x\n",
++ mod->path, DLNPair(mod->h_root), mod->perm);
++ SiMustWriteLock(sb);
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ IiMustWriteLock(root->d_inode);
++
++ bindex = au_find_dbindex(root, mod->h_root);
++ if (unlikely(bindex < 0)) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ Err("%s no such branch\n", mod->path);
++ goto out;
++ }
++ LKTRTrace("bindex b%d\n", bindex);
++
++ hidden_dir = mod->h_root->d_inode;
++ err = test_br(sb, hidden_dir, mod->perm, mod->path);
++ if (unlikely(err))
++ goto out;
++
++ br = stobr(sb, bindex);
++ if (unlikely(br->br_perm == mod->perm))
++ return 0; /* success */
++
++ if (br_writable(br->br_perm)) {
++#if 1
++ /* remove whiteout base */
++ //todo: mod->perm?
++ err = init_br_wh(sb, bindex, br, AuBr_RO, mod->h_root,
++ br->br_mnt);
++ if (unlikely(err))
++ goto out;
++#else
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++#endif
++
++ if (!br_writable(mod->perm)) {
++ /* rw --> ro, file might be mmapped */
++ struct file *file, *hf;
++
++#if 1 // test here
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++
++ // no need file_list_lock() since sbinfo is locked
++ //file_list_lock();
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++ fi_read_lock(file);
++ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE)
++ || fbstart(file) != bindex) {
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ continue;
++ }
++
++ // todo: already flushed?
++ hf = au_h_fptr(file);
++ hf->f_flags = au_file_roflags(hf->f_flags);
++ hf->f_mode &= ~FMODE_WRITE;
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ }
++ //file_list_unlock();
++
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++#endif
++ }
++ }
++
++ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++ br->br_perm = mod->perm;
++ return err; /* success */
++
++ out:
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/branch.h linux-2.6.22.1/fs/aufs/branch.h
+--- linux-2.6.22.1.oorig/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/branch.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,235 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: branch.h,v 1.30 2007/05/14 03:41:51 sfjro Exp $ */
++
++#ifndef __AUFS_BRANCH_H__
++#define __AUFS_BRANCH_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "super.h"
++
++/* protected by superblock rwsem */
++struct aufs_branch {
++ struct file *br_xino;
++ readf_t br_xino_read;
++ writef_t br_xino_write;
++
++ aufs_bindex_t br_id;
++
++ int br_perm;
++ struct vfsmount *br_mnt;
++ atomic_t br_count;
++
++ /* whiteout base */
++ struct aufs_rwsem br_wh_rwsem;
++ struct dentry *br_wh;
++ atomic_t br_wh_running;
++
++ /* pseudo-link dir */
++ struct dentry *br_plink;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* branch permission and attribute */
++enum {
++ AuBr_RW, /* writable, linkable wh */
++ AuBr_RO, /* readonly, no wh */
++ AuBr_RR, /* natively readonly, no wh */
++
++ AuBr_RWNoLinkWH, /* un-linkable whiteouts */
++
++ AuBr_ROWH,
++ AuBr_RRWH, /* whiteout-able */
++
++ AuBr_Last
++};
++
++static inline int br_writable(int brperm)
++{
++ return (brperm == AuBr_RW
++ || brperm == AuBr_RWNoLinkWH);
++}
++
++static inline int br_whable(int brperm)
++{
++ return (brperm == AuBr_RW
++ || brperm == AuBr_ROWH
++ || brperm == AuBr_RRWH);
++}
++
++static inline int br_linkable_wh(int brperm)
++{
++ return (brperm == AuBr_RW);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define _AuNoNfsBranchMsg "NFS branch is not supported"
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,15)
++#define AuNoNfsBranch
++#define AuNoNfsBranchMsg _AuNoNfsBranchMsg
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) \
++ && !defined(CONFIG_AUFS_LHASH_PATCH)
++#define AuNoNfsBranch
++#define AuNoNfsBranchMsg _AuNoNfsBranchMsg \
++ ", try lhash.patch and CONFIG_AUFS_LHASH_PATCH"
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_sbinfo;
++void free_branches(struct aufs_sbinfo *sinfo);
++int br_rdonly(struct aufs_branch *br);
++int find_brindex(struct super_block *sb, aufs_bindex_t br_id);
++int find_rw_br(struct super_block *sb, aufs_bindex_t bend);
++int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend);
++struct opt_add;
++int br_add(struct super_block *sb, struct opt_add *add, int remount);
++struct opt_del;
++int br_del(struct super_block *sb, struct opt_del *del, int remount);
++struct opt_mod;
++int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
++ int *do_update);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int br_count(struct aufs_branch *br)
++{
++ return atomic_read(&br->br_count);
++}
++
++static inline void br_get(struct aufs_branch *br)
++{
++ atomic_inc(&br->br_count);
++}
++
++static inline void br_put(struct aufs_branch *br)
++{
++ atomic_dec(&br->br_count);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Superblock to branch */
++static inline aufs_bindex_t sbr_id(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_id;
++}
++
++static inline
++struct vfsmount *sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_mnt;
++}
++
++static inline
++struct super_block *sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return sbr_mnt(sb, bindex)->mnt_sb;
++}
++
++#if 0
++static inline int sbr_count(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return br_count(stobr(sb, bindex));
++}
++
++static inline void sbr_get(struct super_block *sb, aufs_bindex_t bindex)
++{
++ br_get(stobr(sb, bindex));
++}
++#endif
++
++static inline void sbr_put(struct super_block *sb, aufs_bindex_t bindex)
++{
++ br_put(stobr(sb, bindex));
++}
++
++static inline int sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return stobr(sb, bindex)->br_perm;
++}
++
++static inline int sbr_is_whable(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return br_whable(sbr_perm(sb, bindex));
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_LHASH_PATCH
++static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
++{
++ if (!au_is_nfs(h_mnt->mnt_sb))
++ return NULL;
++ return h_mnt;
++}
++
++/* it doesn't mntget() */
++static inline
++struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_do_nfsmnt(sbr_mnt(sb, bindex));
++}
++#else
++static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
++{
++ return NULL;
++}
++
++static inline
++struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return NULL;
++}
++#endif /* CONFIG_AUFS_LHASH_PATCH */
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * br_wh_read_lock, br_wh_write_lock
++ * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
++ */
++SimpleRwsemFuncs(br_wh, struct aufs_branch *br, br->br_wh_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define BrWhMustReadLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustReadLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#define BrWhMustWriteLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustWriteLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#define BrWhMustAnyLock(br) do { \
++ /* SiMustAnyLock(sb); */ \
++ RwMustAnyLock(&(br)->br_wh_rwsem); \
++} while (0)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_BRANCH_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/cpup.c linux-2.6.22.1/fs/aufs/cpup.c
+--- linux-2.6.22.1.oorig/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/cpup.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,773 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: cpup.c,v 1.37 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++/* violent cpup_attr_*() functions don't care inode lock */
++void au_cpup_attr_timesizes(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++ //IMustLock(!hidden_inode);
++
++ inode->i_atime = hidden_inode->i_atime;
++ inode->i_mtime = hidden_inode->i_mtime;
++ inode->i_ctime = hidden_inode->i_ctime;
++ spin_lock(&inode->i_lock);
++ i_size_write(inode, i_size_read(hidden_inode));
++ inode->i_blocks = hidden_inode->i_blocks;
++ spin_unlock(&inode->i_lock);
++}
++
++void au_cpup_attr_nlink(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ DEBUG_ON(!inode->i_mode);
++
++ h_inode = au_h_iptr(inode);
++ inode->i_nlink = h_inode->i_nlink;
++
++ /*
++ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
++ * it may includes whplink directory.
++ */
++ if (unlikely(S_ISDIR(h_inode->i_mode))) {
++ aufs_bindex_t bindex, bend;
++ bend = ibend(inode);
++ for (bindex = ibstart(inode) + 1; bindex <= bend; bindex++) {
++ h_inode = au_h_iptr_i(inode, bindex);
++ if (h_inode)
++ au_add_nlink(inode, h_inode);
++ }
++ }
++}
++
++void au_cpup_attr_changable(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++
++ inode->i_mode = hidden_inode->i_mode;
++ inode->i_uid = hidden_inode->i_uid;
++ inode->i_gid = hidden_inode->i_gid;
++ au_cpup_attr_timesizes(inode);
++
++ //??
++ inode->i_flags = hidden_inode->i_flags;
++}
++
++void au_cpup_igen(struct inode *inode, struct inode *h_inode)
++{
++ inode->i_generation = h_inode->i_generation;
++ itoii(inode)->ii_hsb1 = h_inode->i_sb;
++}
++
++void au_cpup_attr_all(struct inode *inode)
++{
++ struct inode *hidden_inode;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ //IMustLock(inode);
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode);
++
++ au_cpup_attr_changable(inode);
++ if (inode->i_nlink > 0)
++ au_cpup_attr_nlink(inode);
++
++ switch (inode->i_mode & S_IFMT) {
++ case S_IFBLK:
++ case S_IFCHR:
++ inode->i_rdev = hidden_inode->i_rdev;
++ }
++ inode->i_blkbits = hidden_inode->i_blkbits;
++ au_cpup_attr_blksize(inode, hidden_inode);
++ au_cpup_igen(inode, hidden_inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
++
++/* keep the timestamps of the parent dir when cpup */
++void dtime_store(struct dtime *dt, struct dentry *dentry,
++ struct dentry *hidden_dentry)
++{
++ struct inode *inode;
++
++ TraceEnter();
++ DEBUG_ON(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
++
++ dt->dt_dentry = dentry;
++ dt->dt_h_dentry = hidden_dentry;
++ inode = hidden_dentry->d_inode;
++ dt->dt_atime = inode->i_atime;
++ dt->dt_mtime = inode->i_mtime;
++ //smp_mb();
++}
++
++// todo: remove extra parameter
++void dtime_revert(struct dtime *dt, int h_parent_is_locked)
++{
++ struct iattr attr;
++ int err;
++ struct dentry *dentry;
++
++ LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
++
++ attr.ia_atime = dt->dt_atime;
++ attr.ia_mtime = dt->dt_mtime;
++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
++ | ATTR_ATIME | ATTR_ATIME_SET;
++ //smp_mb();
++ dentry = NULL;
++ if (!h_parent_is_locked /* && !IS_ROOT(dt->dt_dentry) */)
++ dentry = dt->dt_dentry;
++ err = vfsub_notify_change(dt->dt_h_dentry, &attr,
++ need_dlgt(dt->dt_dentry->d_sb));
++ if (unlikely(err))
++ Warn("restoring timestamps failed(%d). ignored\n", err);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
++ int dlgt)
++{
++ int err;
++ struct iattr ia;
++ struct inode *hidden_isrc, *hidden_idst;
++
++ LKTRTrace("%.*s\n", DLNPair(hidden_dst));
++ hidden_idst = hidden_dst->d_inode;
++ //IMustLock(hidden_idst);
++ hidden_isrc = hidden_src->d_inode;
++ //IMustLock(hidden_isrc);
++
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
++ | ATTR_ATIME | ATTR_MTIME
++ | ATTR_ATIME_SET | ATTR_MTIME_SET;
++ ia.ia_mode = hidden_isrc->i_mode;
++ ia.ia_uid = hidden_isrc->i_uid;
++ ia.ia_gid = hidden_isrc->i_gid;
++ ia.ia_atime = hidden_isrc->i_atime;
++ ia.ia_mtime = hidden_isrc->i_mtime;
++ err = vfsub_notify_change(hidden_dst, &ia, dlgt);
++ //if (LktrCond) err = -1;
++ if (!err)
++ hidden_idst->i_flags = hidden_isrc->i_flags; //??
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * to support a sparse file which is opened with O_APPEND,
++ * we need to close the file.
++ */
++static int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len)
++{
++ int err, i, sparse;
++ struct super_block *sb;
++ struct inode *hidden_inode;
++ enum {SRC, DST};
++ struct {
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ struct dentry *dentry;
++ struct file *file;
++ void *label, *label_file;
++ } *h, hidden[] = {
++ {
++ .bindex = bsrc,
++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out,
++ .label_file = &&out_src_file
++ },
++ {
++ .bindex = bdst,
++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out_src_file,
++ .label_file = &&out_dst_file
++ }
++ };
++
++ LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
++ DLNPair(dentry), bdst, bsrc, len);
++ DEBUG_ON(bsrc <= bdst);
++ DEBUG_ON(!len);
++ sb = dentry->d_sb;
++ DEBUG_ON(test_ro(sb, bdst, dentry->d_inode));
++ // bsrc branch can be ro/rw.
++
++ h = hidden;
++ for (i = 0; i < 2; i++, h++) {
++ h->dentry = au_h_dptr_i(dentry, h->bindex);
++ DEBUG_ON(!h->dentry);
++ hidden_inode = h->dentry->d_inode;
++ DEBUG_ON(!hidden_inode || !S_ISREG(hidden_inode->i_mode));
++ h->file = hidden_open(dentry, h->bindex, h->flags);
++ //if (LktrCond)
++ //{fput(h->file); sbr_put(sb, h->bindex); h->file = ERR_PTR(-1);}
++ err = PTR_ERR(h->file);
++ if (IS_ERR(h->file))
++ goto *h->label;
++ err = -EINVAL;
++ if (unlikely(!h->file->f_op))
++ goto *h->label_file;
++ }
++
++ /* stop updating while we copyup */
++ IMustLock(hidden[SRC].dentry->d_inode);
++ sparse = 0;
++ err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb,
++ &sparse);
++
++ /* sparse file: update i_blocks next time */
++ if (unlikely(!err && sparse))
++ d_drop(dentry);
++
++ out_dst_file:
++ fput(hidden[DST].file);
++ sbr_put(sb, hidden[DST].bindex);
++ out_src_file:
++ fput(hidden[SRC].file);
++ sbr_put(sb, hidden[SRC].bindex);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++// unnecessary?
++unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
++{
++ if (unlikely(parent && IS_ROOT(parent)))
++ init |= CPUP_LOCKED_GHDIR;
++ return init;
++}
++
++/* return with hidden dst inode is locked */
++static int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ int dlgt)
++{
++ int err, isdir, symlen;
++ struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
++ struct inode *hidden_inode, *hidden_dir, *dir;
++ struct dtime dt;
++ umode_t mode;
++ char *sym;
++ mm_segment_t old_fs;
++ const int do_dt = flags & CPUP_DTIME;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++ sb = dentry->d_sb;
++ DEBUG_ON(bdst >= bsrc || test_ro(sb, bdst, NULL));
++ // bsrc branch can be ro/rw.
++
++ hidden_src = au_h_dptr_i(dentry, bsrc);
++ DEBUG_ON(!hidden_src);
++ hidden_inode = hidden_src->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ /* stop refrencing while we are creating */
++ //parent = dget_parent(dentry);
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ hidden_dst = au_h_dptr_i(dentry, bdst);
++ DEBUG_ON(hidden_dst && hidden_dst->d_inode);
++ //hidden_parent = dget_parent(hidden_dst);
++ hidden_parent = hidden_dst->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ if (do_dt)
++ dtime_store(&dt, parent, hidden_parent);
++
++ isdir = 0;
++ mode = hidden_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ /* stop updating while we are referencing */
++ IMustLock(hidden_inode);
++ err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
++ dlgt);
++ //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ if (!err) {
++ loff_t l = i_size_read(hidden_inode);
++ if (len == -1 || l < len)
++ len = l;
++ if (len) {
++ err = cpup_regular(dentry, bdst, bsrc, len);
++ //if (LktrCond) err = -1;
++ }
++ if (unlikely(err)) {
++ int rerr;
++ rerr = vfsub_unlink(hidden_dir, hidden_dst,
++ dlgt);
++ if (rerr) {
++ IOErr("failed unlinking cpup-ed %.*s"
++ "(%d, %d)\n",
++ DLNPair(hidden_dst), err, rerr);
++ err = -EIO;
++ }
++ }
++ }
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ err = vfsub_mkdir(hidden_dir, hidden_dst, mode, dlgt);
++ //if (LktrCond) {vfs_rmdir(hidden_dir, hidden_dst); err = -1;}
++ if (!err) {
++ /* setattr case: dir is not locked */
++ if (0 && ibstart(dir) == bdst)
++ au_cpup_attr_nlink(dir);
++ au_cpup_attr_nlink(dentry->d_inode);
++ }
++ break;
++ case S_IFLNK:
++ err = -ENOMEM;
++ sym = __getname();
++ //if (LktrCond) {__putname(sym); sym = NULL;}
++ if (unlikely(!sym))
++ break;
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = symlen = hidden_inode->i_op->readlink
++ (hidden_src, (char __user*)sym, PATH_MAX);
++ //if (LktrCond) err = symlen = -1;
++ set_fs(old_fs);
++ if (symlen > 0) {
++ sym[symlen] = 0;
++ err = vfsub_symlink(hidden_dir, hidden_dst, sym, mode,
++ dlgt);
++ //if (LktrCond)
++ //{vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ }
++ __putname(sym);
++ break;
++ case S_IFCHR:
++ case S_IFBLK:
++ DEBUG_ON(!capable(CAP_MKNOD));
++ /*FALLTHROUGH*/
++ case S_IFIFO:
++ case S_IFSOCK:
++ err = vfsub_mknod(hidden_dir, hidden_dst, mode,
++ hidden_inode->i_rdev, dlgt);
++ //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
++ break;
++ default:
++ IOErr("Unknown inode type 0%o\n", mode);
++ err = -EIO;
++ }
++
++ if (do_dt)
++ dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
++ //dput(parent);
++ //dput(hidden_parent);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the @dentry from @bsrc to @bdst.
++ * the caller must set the both of hidden dentries.
++ * @len is for trucating when it is -1 copyup the entire file.
++ */
++int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
++ loff_t len, unsigned int flags)
++{
++ int err, rerr, isdir, dlgt;
++ struct dentry *hidden_src, *hidden_dst, *parent;//, *h_parent;
++ struct inode *dst_inode, *hidden_dir, *inode, *src_inode;
++ struct super_block *sb;
++ aufs_bindex_t old_ibstart;
++ struct dtime dt;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++ sb = dentry->d_sb;
++ DEBUG_ON(bsrc <= bdst);
++ hidden_dst = au_h_dptr_i(dentry, bdst);
++ DEBUG_ON(!hidden_dst || hidden_dst->d_inode);
++ //h_parent = dget_parent(hidden_dst);
++ //hidden_dir = h_parent->d_inode;
++ hidden_dir = hidden_dst->d_parent->d_inode;
++ IMustLock(hidden_dir);
++ hidden_src = au_h_dptr_i(dentry, bsrc);
++ DEBUG_ON(!hidden_src || !hidden_src->d_inode);
++ inode = dentry->d_inode;
++ IiMustWriteLock(inode);
++
++ dlgt = need_dlgt(sb);
++ dst_inode = au_h_iptr_i(inode, bdst);
++ if (unlikely(dst_inode)) {
++ if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
++ err = -EIO;
++ IOErr("i%lu exists on a upper branch "
++ "but plink is disabled\n", inode->i_ino);
++ goto out;
++ }
++
++ if (dst_inode->i_nlink) {
++ hidden_src = lkup_plink(sb, bdst, inode);
++ err = PTR_ERR(hidden_src);
++ if (IS_ERR(hidden_src))
++ goto out;
++ DEBUG_ON(!hidden_src->d_inode);
++ // vfs_link() does lock the inode
++ err = vfsub_link(hidden_src, hidden_dir, hidden_dst, dlgt);
++ dput(hidden_src);
++ goto out;
++ } else
++ /* udba work */
++ au_update_brange(inode, 1);
++ }
++
++ old_ibstart = ibstart(inode);
++ err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
++ if (unlikely(err))
++ goto out;
++ dst_inode = hidden_dst->d_inode;
++ hi_lock_child2(dst_inode);
++
++ //todo: test dlgt
++ err = cpup_iattr(hidden_dst, hidden_src, dlgt);
++ //if (LktrCond) err = -1;
++#if 0 // xattr
++ if (0 && !err)
++ err = cpup_xattrs(hidden_src, hidden_dst);
++#endif
++ isdir = S_ISDIR(dst_inode->i_mode);
++ if (!err) {
++ if (bdst < old_ibstart)
++ set_ibstart(inode, bdst);
++ set_h_iptr(inode, bdst, igrab(dst_inode),
++ au_hi_flags(inode, isdir));
++ i_unlock(dst_inode);
++ src_inode = hidden_src->d_inode;
++ if (!isdir) {
++ if (src_inode->i_nlink > 1
++ && au_flag_test(sb, AuFlag_PLINK))
++ append_plink(sb, inode, hidden_dst, bdst);
++ else {
++ /* braces are added to stop a warning */
++ ;//xino_write0(sb, bsrc, src_inode->i_ino);
++ /* ignore this error */
++ }
++ }
++ //goto out; /* success */
++ return 0; /* success */
++ }
++
++ /* revert */
++ i_unlock(dst_inode);
++ parent = dget_parent(dentry);
++ //dtime_store(&dt, parent, h_parent);
++ dtime_store(&dt, parent, hidden_dst->d_parent);
++ dput(parent);
++ if (!isdir)
++ rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
++ else
++ rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
++ //rerr = -1;
++ dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
++ if (rerr) {
++ IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ //dput(h_parent);
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_single_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst, bsrc;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void call_cpup_single(void *args)
++{
++ struct cpup_single_args *a = args;
++ *a->errp = cpup_single(a->dentry, a->bdst, a->bsrc, a->len, a->flags);
++}
++
++int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags)
++{
++ int err;
++ struct dentry *hidden_dentry;
++ umode_t mode;
++
++ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
++ flags);
++
++ hidden_dentry = au_h_dptr_i(dentry, bsrc);
++ mode = hidden_dentry->d_inode->i_mode & S_IFMT;
++ if ((mode != S_IFCHR && mode != S_IFBLK)
++ || capable(CAP_MKNOD))
++ err = cpup_single(dentry, bdst, bsrc, len, flags);
++ else {
++ struct cpup_single_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .bsrc = bsrc,
++ .len = len,
++ .flags = flags
++ };
++ au_wkq_wait(call_cpup_single, &args, /*dlgt*/0);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the @dentry from the first active hidden branch to @bdst,
++ * using cpup_single().
++ */
++int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err;
++ struct inode *inode;
++ aufs_bindex_t bsrc, bend;
++
++ LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), bdst, len, flags);
++ inode = dentry->d_inode;
++ DEBUG_ON(!S_ISDIR(inode->i_mode) && dbstart(dentry) < bdst);
++
++ bend = dbend(dentry);
++ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
++ if (au_h_dptr_i(dentry, bsrc))
++ break;
++ DEBUG_ON(!au_h_dptr_i(dentry, bsrc));
++
++ err = lkup_neg(dentry, bdst);
++ //err = -1;
++ if (!err) {
++ err = cpup_single(dentry, bdst, bsrc, len, flags);
++ if (!err)
++ return 0; /* success */
++
++ /* revert */
++ set_h_dptr(dentry, bdst, NULL);
++ set_dbstart(dentry, bsrc);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_simple_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void call_cpup_simple(void *args)
++{
++ struct cpup_simple_args *a = args;
++ *a->errp = cpup_simple(a->dentry, a->bdst, a->len, a->flags);
++}
++
++int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err, do_sio, dlgt;
++ //struct dentry *parent;
++ struct inode *hidden_dir, *dir;
++
++ LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
++ DLNPair(dentry), bdst, len, flags);
++
++ //parent = dget_parent(dentry);
++ //dir = parent->d_inode;
++ dir = dentry->d_parent->d_inode;
++ hidden_dir = au_h_iptr_i(dir, bdst);
++ dlgt = need_dlgt(dir->i_sb);
++ do_sio = au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, dlgt);
++ if (!do_sio) {
++ umode_t mode = dentry->d_inode->i_mode & S_IFMT;
++ do_sio = ((mode == S_IFCHR || mode == S_IFBLK)
++ && !capable(CAP_MKNOD));
++ }
++ if (!do_sio)
++ err = cpup_simple(dentry, bdst, len, flags);
++ else {
++ struct cpup_simple_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .flags = flags
++ };
++ au_wkq_wait(call_cpup_simple, &args, /*dlgt*/0);
++ }
++
++ //dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++//todo: dcsub
++/* cf. revalidate function in file.c */
++int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *d, *parent, *hidden_parent;
++ unsigned int udba;
++
++ LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
++ DLNPair(dentry), bdst, parent_ino(dentry), locked);
++ sb = dentry->d_sb;
++ DEBUG_ON(test_ro(sb, bdst, NULL));
++ parent = dentry->d_parent;
++ IiMustWriteLock(parent->d_inode);
++ if (unlikely(IS_ROOT(parent)))
++ return 0;
++ if (locked) {
++ DiMustAnyLock(locked);
++ IiMustAnyLock(locked->d_inode);
++ }
++
++ /* slow loop, keep it simple and stupid */
++ err = 0;
++ udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++ while (1) {
++ parent = dentry->d_parent; // dget_parent()
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ if (hidden_parent)
++ return 0; /* success */
++
++ /* find top dir which is needed to cpup */
++ do {
++ d = parent;
++ parent = d->d_parent; // dget_parent()
++ if (parent != locked)
++ di_read_lock_parent3(parent, !AUFS_I_RLOCK);
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ if (parent != locked)
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ } while (!hidden_parent);
++
++ if (d != dentry->d_parent)
++ di_write_lock_child3(d);
++
++ /* somebody else might create while we were sleeping */
++ if (!au_h_dptr_i(d, bdst) || !au_h_dptr_i(d, bdst)->d_inode) {
++ struct inode *h_dir = hidden_parent->d_inode,
++ *dir = parent->d_inode,
++ *h_gdir, *gdir;
++
++ if (au_h_dptr_i(d, bdst))
++ au_update_dbstart(d);
++ //DEBUG_ON(dbstart(d) <= bdst);
++ if (parent != locked)
++ di_read_lock_parent3(parent, AUFS_I_RLOCK);
++ h_gdir = gdir = NULL;
++ if (unlikely(udba && !IS_ROOT(parent))) {
++ gdir = parent->d_parent->d_inode;
++ h_gdir = hidden_parent->d_parent->d_inode;
++ hgdir_lock(h_gdir, gdir, bdst);
++ }
++ hdir_lock(h_dir, dir, bdst);
++ err = sio_cpup_simple(d, bdst, -1,
++ au_flags_cpup(CPUP_DTIME,
++ parent));
++ //if (LktrCond) err = -1;
++ hdir_unlock(h_dir, dir, bdst);
++ if (unlikely(gdir))
++ hdir_unlock(h_gdir, gdir, bdst);
++ if (parent != locked)
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++
++ if (d != dentry->d_parent)
++ di_write_unlock(d);
++ if (unlikely(err))
++ break;
++ }
++
++// out:
++ TraceErr(err);
++ return err;
++}
++
++int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *locked)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *dir;
++
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
++ DLNPair(dentry), bdst, dir->i_ino, locked);
++ DiMustReadLock(parent);
++ IiMustReadLock(dir);
++
++ if (au_h_iptr_i(dir, bdst))
++ return 0;
++
++ err = 0;
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ di_write_lock_parent(parent);
++ if (au_h_iptr_i(dir, bdst))
++ goto out;
++
++ err = cpup_dirs(dentry, bdst, locked);
++
++ out:
++ di_downgrade_lock(parent, AUFS_I_RLOCK);
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/cpup.h linux-2.6.22.1/fs/aufs/cpup.h
+--- linux-2.6.22.1.oorig/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/cpup.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,72 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: cpup.h,v 1.15 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_CPUP_H__
++#define __AUFS_CPUP_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++static inline
++void au_cpup_attr_blksize(struct inode *inode, struct inode *h_inode)
++{
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++ inode->i_blksize = h_inode->i_blksize;
++#endif
++}
++
++void au_cpup_attr_timesizes(struct inode *inode);
++void au_cpup_attr_nlink(struct inode *inode);
++void au_cpup_attr_changable(struct inode *inode);
++void au_cpup_igen(struct inode *inode, struct inode *h_inode);
++void au_cpup_attr_all(struct inode *inode);
++
++#define CPUP_DTIME 1 // do dtime_store/revert
++// todo: remove this
++#define CPUP_LOCKED_GHDIR 2 // grand parent hidden dir is locked
++unsigned int au_flags_cpup(unsigned int init, struct dentry *parent);
++
++int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
++ loff_t len, unsigned int flags);
++int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags);
++int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++
++int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked);
++int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *locked);
++
++/* keep timestamps when copyup */
++struct dtime {
++ struct dentry *dt_dentry, *dt_h_dentry;
++ struct timespec dt_atime, dt_mtime;
++};
++void dtime_store(struct dtime *dt, struct dentry *dentry,
++ struct dentry *h_dentry);
++void dtime_revert(struct dtime *dt, int h_parent_is_locked);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_CPUP_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dcsub.c linux-2.6.22.1/fs/aufs/dcsub.c
+--- linux-2.6.22.1.oorig/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dcsub.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,175 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dcsub.c,v 1.3 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static void au_dpage_free(struct au_dpage *dpage)
++{
++ int i;
++
++ TraceEnter();
++ DEBUG_ON(!dpage);
++
++ for (i = 0; i < dpage->ndentry; i++)
++ dput(dpage->dentries[i]);
++ free_page((unsigned long)dpage->dentries);
++}
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
++{
++ int err;
++ void *p;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
++ if (unlikely(!dpages->dpages))
++ goto out;
++ p = (void*)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out_dpages;
++ dpages->dpages[0].ndentry = 0;
++ dpages->dpages[0].dentries = p;
++ dpages->ndpage = 1;
++ return 0; /* success */
++
++ out_dpages:
++ kfree(dpages->dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++void au_dpages_free(struct au_dcsub_pages *dpages)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < dpages->ndpage; i++)
++ au_dpage_free(dpages->dpages + i);
++ kfree(dpages->dpages);
++}
++
++static int au_dpages_append(struct au_dcsub_pages *dpages,
++ struct dentry *dentry, gfp_t gfp)
++{
++ int err, sz;
++ struct au_dpage *dpage;
++ void *p;
++
++ //TraceEnter();
++
++ dpage = dpages->dpages + dpages->ndpage - 1;
++ DEBUG_ON(!dpage);
++ sz = PAGE_SIZE/sizeof(dentry);
++ if (unlikely(dpage->ndentry >= sz)) {
++ LKTRLabel(new dpage);
++ err = -ENOMEM;
++ sz = dpages->ndpage * sizeof(*dpages->dpages);
++ p = au_kzrealloc(dpages->dpages, sz,
++ sz + sizeof(*dpages->dpages), gfp);
++ if (unlikely(!p))
++ goto out;
++ dpage = dpages->dpages + dpages->ndpage;
++ p = (void*)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out;
++ dpage->ndentry = 0;
++ dpage->dentries = p;
++ dpages->ndpage++;
++ }
++
++ dpage->dentries[dpage->ndentry++] = dget(dentry);
++ return 0; /* success */
++
++ out:
++ //TraceErr(err);
++ return err;
++}
++
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg)
++{
++ int err;
++ struct dentry *this_parent = root;
++ struct list_head *next;
++ struct super_block *sb = root->d_sb;
++
++ TraceEnter();
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ repeat:
++ next = this_parent->d_subdirs.next;
++ resume:
++ if (this_parent->d_sb == sb
++ && !IS_ROOT(this_parent)
++ && atomic_read(&this_parent->d_count)
++ && this_parent->d_inode
++ && (!test || test(this_parent, arg))) {
++ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++
++ while (next != &this_parent->d_subdirs) {
++ struct list_head *tmp = next;
++ struct dentry *dentry = list_entry(tmp, struct dentry, D_CHILD);
++ next = tmp->next;
++ if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode))
++ continue;
++ if (!list_empty(&dentry->d_subdirs)) {
++ this_parent = dentry;
++ goto repeat;
++ }
++ if (dentry->d_sb == sb
++ && atomic_read(&dentry->d_count)
++ && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ }
++
++ if (this_parent != root) {
++ next = this_parent->D_CHILD.next;
++ this_parent = this_parent->d_parent;
++ goto resume;
++ }
++ out:
++ spin_unlock(&dcache_lock);
++#if 0
++ if (!err) {
++ int i, j;
++ j = 0;
++ for (i = 0; i < dpages->ndpage; i++) {
++ if ((dpages->dpages + i)->ndentry)
++ Dbg("%d: %d\n", i, (dpages->dpages + i)->ndentry);
++ j += (dpages->dpages + i)->ndentry;
++ }
++ if (j)
++ Dbg("ndpage %d, %d\n", dpages->ndpage, j);
++ }
++#endif
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dcsub.h linux-2.6.22.1/fs/aufs/dcsub.h
+--- linux-2.6.22.1.oorig/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dcsub.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dcsub.h,v 1.2 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DCSUB_H__
++#define __AUFS_DCSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/dcache.h>
++
++struct au_dpage {
++ int ndentry;
++ struct dentry **dentries;
++};
++
++struct au_dcsub_pages {
++ int ndpage;
++ struct au_dpage *dpages;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
++void au_dpages_free(struct au_dcsub_pages *dpages);
++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DCSUB_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/debug.c linux-2.6.22.1/fs/aufs/debug.c
+--- linux-2.6.22.1.oorig/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/debug.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,262 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: debug.c,v 1.27 2007/04/30 05:48:23 sfjro Exp $ */
++
++#include "aufs.h"
++
++atomic_t aufs_cond = ATOMIC_INIT(0);
++
++#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
++#define dpri(fmt, arg...) \
++ do {if (LktrCond) printk(KERN_DEBUG fmt, ##arg);} while (0)
++#else
++#define dpri(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++void au_dpri_whlist(struct aufs_nhash *whlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ dpri("b%d, %.*s, %d\n",
++ tpos->wh_bindex,
++ tpos->wh_str.len, tpos->wh_str.name,
++ tpos->wh_str.len);
++ }
++}
++
++void au_dpri_vdir(struct aufs_vdir *vdir)
++{
++ int i;
++ union aufs_deblk_p p;
++ unsigned char *o;
++
++ if (!vdir || IS_ERR(vdir)) {
++ dpri("err %ld\n", PTR_ERR(vdir));
++ return;
++ }
++
++ dpri("nblk %d, deblk %p %d, last{%d, %p}, ver %lu\n",
++ vdir->vd_nblk, vdir->vd_deblk, ksize(vdir->vd_deblk),
++ vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
++ for (i = 0; i < vdir->vd_nblk; i++) {
++ p.deblk = vdir->vd_deblk[i];
++ o = p.p;
++ dpri("[%d]: %p %d\n", i, o, ksize(o));
++#if 0 // verbose
++ int j;
++ for (j = 0; j < 8; j++) {
++ dpri("%p(+%d) {%02x %02x %02x %02x %02x %02x %02x %02x "
++ "%02x %02x %02x %02x %02x %02x %02x %02x}\n",
++ p.p, p.p - o,
++ p.p[0], p.p[1], p.p[2], p.p[3],
++ p.p[4], p.p[5], p.p[6], p.p[7],
++ p.p[8], p.p[9], p.p[10], p.p[11],
++ p.p[12], p.p[13], p.p[14], p.p[15]);
++ p.p += 16;
++ }
++#endif
++ }
++}
++
++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode)
++{
++ if (!inode || IS_ERR(inode)) {
++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
++ return -1;
++ }
++
++ /* the type of i_blocks depends upon CONFIG_LSF */
++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
++ && sizeof(inode->i_blocks) != sizeof(u64));
++ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %Lu, blk %Lu,"
++ " ct %Ld, np %lu, st 0x%lx, g %x\n",
++ bindex,
++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
++ i_size_read(inode), (u64)inode->i_blocks,
++ timespec_to_ns(&inode->i_ctime) & 0x0ffff,
++ inode->i_mapping ? inode->i_mapping->nrpages : 0,
++ inode->i_state, inode->i_generation);
++ return 0;
++}
++
++void au_dpri_inode(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_inode(-1, inode);
++ if (err || !au_is_aufs(inode->i_sb))
++ return;
++
++ iinfo = itoii(inode);
++ if (!iinfo)
++ return;
++ dpri("i-1: bstart %d, bend %d, gen %d\n",
++ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
++ if (iinfo->ii_bstart < 0)
++ return;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
++ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode);
++}
++
++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
++{
++ if (!dentry || IS_ERR(dentry)) {
++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
++ return -1;
++ }
++ dpri("d%d: %.*s/%.*s, %s, cnt %d, flags 0x%x\n",
++ bindex,
++ DLNPair(dentry->d_parent), DLNPair(dentry),
++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
++ atomic_read(&dentry->d_count), dentry->d_flags);
++ do_pri_inode(bindex, dentry->d_inode);
++ return 0;
++}
++
++void au_dpri_dentry(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_dentry(-1, dentry);
++ if (err || !au_is_aufs(dentry->d_sb))
++ return;
++
++ dinfo = dtodi(dentry);
++ if (!dinfo)
++ return;
++ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
++ dinfo->di_bstart, dinfo->di_bend,
++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
++ if (dinfo->di_bstart < 0)
++ return;
++ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
++ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
++}
++
++static int do_pri_file(aufs_bindex_t bindex, struct file *file)
++{
++ char a[32];
++
++ if (!file || IS_ERR(file)) {
++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
++ return -1;
++ }
++ a[0] = 0;
++ if (bindex == -1 && ftofi(file))
++ snprintf(a, sizeof(a), ", mmapped %d", au_is_mmapped(file));
++ dpri("f%d: mode 0x%x, flags 0%o, cnt %d, pos %Lu%s\n",
++ bindex, file->f_mode, file->f_flags, file_count(file),
++ file->f_pos, a);
++ do_pri_dentry(bindex, file->f_dentry);
++ return 0;
++}
++
++void au_dpri_file(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_file(-1, file);
++ if (err || !file->f_dentry || !au_is_aufs(file->f_dentry->d_sb))
++ return;
++
++ finfo = ftofi(file);
++ if (!finfo)
++ return;
++ if (finfo->fi_bstart < 0)
++ return;
++ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
++ struct aufs_hfile *hf;
++ //dpri("bindex %d\n", bindex);
++ hf = finfo->fi_hfile + bindex;
++ do_pri_file(bindex, hf ? hf->hf_file : NULL);
++ }
++}
++
++static int do_pri_br(aufs_bindex_t bindex, struct aufs_branch *br)
++{
++ struct vfsmount *mnt;
++ struct super_block *sb;
++
++ if (!br || IS_ERR(br)
++ || !(mnt = br->br_mnt) || IS_ERR(mnt)
++ || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
++ return -1;
++ }
++
++ dpri("s%d: {perm 0x%x, cnt %d}, "
++ "%s, flags 0x%lx, cnt(BIAS) %d, active %d, xino %p %p\n",
++ bindex, br->br_perm, br_count(br),
++ au_sbtype(sb), sb->s_flags, sb->s_count - S_BIAS,
++ atomic_read(&sb->s_active), br->br_xino,
++ br->br_xino ? br->br_xino->f_dentry : NULL);
++ return 0;
++}
++
++void au_dpri_sb(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ aufs_bindex_t bindex;
++ int err;
++ struct vfsmount mnt = {.mnt_sb = sb};
++ struct aufs_branch fake = {
++ .br_perm = 0,
++ .br_mnt = &mnt,
++ .br_count = ATOMIC_INIT(0),
++ .br_xino = NULL
++ };
++
++ atomic_set(&fake.br_count, 0);
++ err = do_pri_br(-1, &fake);
++ dpri("dev 0x%x\n", sb->s_dev);
++ if (err || !au_is_aufs(sb))
++ return;
++
++ sbinfo = stosi(sb);
++ if (!sbinfo)
++ return;
++ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) {
++ //dpri("bindex %d\n", bindex);
++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void DbgSleep(int sec)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ Dbg("sleep %d sec\n", sec);
++ wait_event_timeout(wq, 0, sec * HZ);
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/debug.h linux-2.6.22.1/fs/aufs/debug.h
+--- linux-2.6.22.1.oorig/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/debug.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,129 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: debug.h,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DEBUG_H__
++#define __AUFS_DEBUG_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++
++#ifdef CONFIG_AUFS_DEBUG
++#define DEBUG_ON(a) BUG_ON(a)
++extern atomic_t aufs_cond;
++#define au_debug_on() atomic_inc(&aufs_cond)
++#define au_debug_off() atomic_dec(&aufs_cond)
++#define au_is_debug() atomic_read(&aufs_cond)
++#else
++#define DEBUG_ON(a) /* */
++#define au_debug_on() /* */
++#define au_debug_off() /* */
++#define au_is_debug() 0
++#endif
++
++#define MtxMustLock(mtx) DEBUG_ON(!mutex_is_locked(mtx))
++
++/* ---------------------------------------------------------------------- */
++
++/* debug print */
++#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
++#include <linux/lktr.h>
++#ifdef CONFIG_AUFS_DEBUG
++#undef LktrCond
++#define LktrCond unlikely((lktr_cond && lktr_cond()) || au_is_debug())
++#endif
++#else
++#define LktrCond au_is_debug()
++#define LKTRDumpVma(pre, vma, suf) /* */
++#define LKTRDumpStack() /* */
++#define LKTRTrace(fmt, args...) do { \
++ if (LktrCond) \
++ Dbg(fmt, ##args); \
++} while (0)
++#define LKTRLabel(label) LKTRTrace("%s\n", #label)
++#endif /* CONFIG_LKTR */
++
++#define TraceErr(e) do { \
++ if (unlikely((e) < 0)) \
++ LKTRTrace("err %d\n", (int)(e)); \
++} while (0)
++#define TraceErrPtr(p) do { \
++ if (IS_ERR(p)) \
++ LKTRTrace("err %ld\n", PTR_ERR(p)); \
++} while (0)
++#define TraceEnter() LKTRLabel(enter)
++
++/* dirty macros for debug print, use with "%.*s" and caution */
++#define LNPair(qstr) (qstr)->len,(qstr)->name
++#define DLNPair(d) LNPair(&(d)->d_name)
++
++/* ---------------------------------------------------------------------- */
++
++#define Dpri(lvl, fmt, arg...) \
++ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
++ __func__, __LINE__, current->comm, current->pid, ##arg)
++#define Dbg(fmt, arg...) Dpri(KERN_DEBUG, fmt, ##arg)
++#define Warn(fmt, arg...) Dpri(KERN_WARNING, fmt, ##arg)
++#define Warn1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) Warn(fmt, ##arg); \
++ } while (0)
++#define Err(fmt, arg...) Dpri(KERN_ERR, fmt, ##arg)
++#define Err1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) Err(fmt, ##arg); \
++ } while (0)
++#define IOErr(fmt, arg...) Err("I/O Error, " fmt, ##arg)
++#define IOErr1(fmt, arg...) do { \
++ static unsigned char c; \
++ if (!c++) IOErr(fmt, ##arg); \
++ } while (0)
++#define IOErrWhck(fmt, arg...) Err("I/O Error, try whck. " fmt, ##arg)
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DEBUG
++struct aufs_nhash;
++void au_dpri_whlist(struct aufs_nhash *whlist);
++struct aufs_vdir;
++void au_dpri_vdir(struct aufs_vdir *vdir);
++void au_dpri_inode(struct inode *inode);
++void au_dpri_dentry(struct dentry *dentry);
++void au_dpri_file(struct file *filp);
++void au_dpri_sb(struct super_block *sb);
++#define DbgWhlist(w) do{LKTRTrace(#w "\n"); au_dpri_whlist(w);}while(0)
++#define DbgVdir(v) do{LKTRTrace(#v "\n"); au_dpri_vdir(v);}while(0)
++#define DbgInode(i) do{LKTRTrace(#i "\n"); au_dpri_inode(i);}while(0)
++#define DbgDentry(d) do{LKTRTrace(#d "\n"); au_dpri_dentry(d);}while(0)
++#define DbgFile(f) do{LKTRTrace(#f "\n"); au_dpri_file(f);}while(0)
++#define DbgSb(sb) do{LKTRTrace(#sb "\n"); au_dpri_sb(sb);}while(0)
++void DbgSleep(int sec);
++#else
++#define DbgWhlist(w) /* */
++#define DbgVdir(v) /* */
++#define DbgInode(i) /* */
++#define DbgDentry(d) /* */
++#define DbgFile(f) /* */
++#define DbgSb(sb) /* */
++#define DbgSleep(sec) /* */
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DEBUG_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dentry.c linux-2.6.22.1/fs/aufs/dentry.c
+--- linux-2.6.22.1.oorig/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dentry.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,946 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dentry.c,v 1.41 2007/05/14 03:38:38 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++#ifdef CONFIG_AUFS_LHASH_PATCH
++
++#ifdef CONFIG_AUFS_DLGT
++struct lookup_hash_args {
++ struct dentry **errp;
++ struct qstr *name;
++ struct dentry *base;
++ struct nameidata *nd;
++};
++
++static void call_lookup_hash(void *args)
++{
++ struct lookup_hash_args *a = args;
++ *a->errp = __lookup_hash(a->name, a->base, a->nd);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++static struct dentry *lkup_hash(const char *name, struct dentry *parent,
++ int len, struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++ char *p;
++ unsigned long hash;
++ struct qstr this;
++ unsigned int c;
++ struct nameidata tmp_nd;
++
++ dentry = ERR_PTR(-EACCES);
++ this.name = name;
++ this.len = len;
++ if (unlikely(!len))
++ goto out;
++
++ p = (void*)name;
++ hash = init_name_hash();
++ while (len--) {
++ c = *p++;
++ if (unlikely(c == '/' || c == '\0'))
++ goto out;
++ hash = partial_name_hash(c, hash);
++ }
++ this.hash = end_name_hash(hash);
++
++ memset(&tmp_nd, 0, sizeof(tmp_nd));
++ tmp_nd.dentry = dget(parent);
++ tmp_nd.mnt = mntget(lkup->nfsmnt);
++#ifndef CONFIG_AUFS_DLGT
++ dentry = __lookup_hash(&this, parent, &tmp_nd);
++#else
++ if (!lkup->dlgt)
++ dentry = __lookup_hash(&this, parent, &tmp_nd);
++ else {
++ struct lookup_hash_args args = {
++ .errp = &dentry,
++ .name = &this,
++ .base = parent,
++ .nd = &tmp_nd
++ };
++ au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
++ }
++#endif
++ path_release(&tmp_nd);
++
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++#elif defined(CONFIG_AUFS_DLGT)
++static struct dentry *lkup_hash(const char *name, struct dentry *parent,
++ int len, struct lkup_args *lkup)
++{
++ return ERR_PTR(-ENOSYS);
++}
++#endif
++
++#ifdef CONFIG_AUFS_DLGT
++struct lookup_one_len_args {
++ struct dentry **errp;
++ const char *name;
++ struct dentry *parent;
++ int len;
++};
++
++static void call_lookup_one_len(void *args)
++{
++ struct lookup_one_len_args *a = args;
++ *a->errp = lookup_one_len(a->name, a->parent, a->len);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
++/* cf. lookup_one_len() in linux/fs/namei.c */
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++
++ LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
++ DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);
++
++ if (!lkup->nfsmnt) {
++#ifndef CONFIG_AUFS_DLGT
++ dentry = lookup_one_len(name, parent, len);
++#else
++ if (!lkup->dlgt)
++ dentry = lookup_one_len(name, parent, len);
++ else {
++ struct lookup_one_len_args args = {
++ .errp = &dentry,
++ .name = name,
++ .parent = parent,
++ .len = len
++ };
++ au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1);
++ }
++#endif
++ } else
++ dentry = lkup_hash(name, parent, len, lkup);
++
++ TraceErrPtr(dentry);
++ return dentry;
++}
++#endif
++
++struct lkup_one_args {
++ struct dentry **errp;
++ const char *name;
++ struct dentry *parent;
++ int len;
++ struct lkup_args *lkup;
++};
++
++static void call_lkup_one(void *args)
++{
++ struct lkup_one_args *a = args;
++ *a->errp = lkup_one(a->name, a->parent, a->len, a->lkup);
++}
++
++/*
++ * returns positive/negative dentry, NULL or an error.
++ * NULL means whiteout-ed or not-found.
++ */
++static struct dentry *do_lookup(struct dentry *hidden_parent,
++ struct dentry *dentry, aufs_bindex_t bindex,
++ struct qstr *wh_name, int allow_neg,
++ mode_t type, int dlgt)
++{
++ struct dentry *hidden_dentry;
++ int wh_found, wh_able, opq;
++ struct inode *hidden_dir, *hidden_inode;
++ struct qstr *name;
++ struct super_block *sb;
++ struct lkup_args lkup = {.dlgt = dlgt};
++
++ LKTRTrace("%.*s/%.*s, b%d, allow_neg %d, type 0%o, dlgt %d\n",
++ DLNPair(hidden_parent), DLNPair(dentry), bindex, allow_neg,
++ type, dlgt);
++ DEBUG_ON(IS_ROOT(dentry));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ wh_found = 0;
++ sb = dentry->d_sb;
++ wh_able = sbr_is_whable(sb, bindex);
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ name = &dentry->d_name;
++ if (unlikely(wh_able)) {
++#if 0 //def CONFIG_AUFS_ROBR
++ if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
++ wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0,
++ &lkup);
++ else
++ wh_found = -EPERM;
++#else
++ wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0, &lkup);
++#endif
++ }
++ //if (LktrCond) wh_found = -1;
++ hidden_dentry = ERR_PTR(wh_found);
++ if (!wh_found)
++ goto real_lookup;
++ if (unlikely(wh_found < 0))
++ goto out;
++
++ /* We found a whiteout */
++ //set_dbend(dentry, bindex);
++ set_dbwh(dentry, bindex);
++ if (!allow_neg)
++ return NULL; /* success */
++
++ real_lookup:
++ // do not superio.
++ hidden_dentry = lkup_one(name->name, hidden_parent, name->len, &lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ if (IS_ERR(hidden_dentry))
++ goto out;
++ DEBUG_ON(d_unhashed(hidden_dentry));
++ hidden_inode = hidden_dentry->d_inode;
++ if (!hidden_inode) {
++ if (!allow_neg)
++ goto out_neg;
++ } else if (wh_found
++ || (type && type != (hidden_inode->i_mode & S_IFMT)))
++ goto out_neg;
++
++ if (dbend(dentry) <= bindex)
++ set_dbend(dentry, bindex);
++ if (dbstart(dentry) == -1 || bindex < dbstart(dentry))
++ set_dbstart(dentry, bindex);
++ set_h_dptr(dentry, bindex, hidden_dentry);
++
++ if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode) || !wh_able)
++ return hidden_dentry; /* success */
++
++ hi_lock_child(hidden_inode);
++ opq = is_diropq(hidden_dentry, &lkup);
++ //if (LktrCond) opq = -1;
++ i_unlock(hidden_inode);
++ if (opq > 0)
++ set_dbdiropq(dentry, bindex);
++ else if (unlikely(opq < 0)) {
++ set_h_dptr(dentry, bindex, NULL);
++ hidden_dentry = ERR_PTR(opq);
++ }
++ goto out;
++
++ out_neg:
++ dput(hidden_dentry);
++ hidden_dentry = NULL;
++ out:
++ TraceErrPtr(hidden_dentry);
++ return hidden_dentry;
++}
++
++/*
++ * returns the number of hidden positive dentries,
++ * otherwise an error.
++ */
++int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
++{
++ int npositive, err, allow_neg, dlgt;
++ struct dentry *parent;
++ aufs_bindex_t bindex, btail;
++ const struct qstr *name = &dentry->d_name;
++ struct qstr whname;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, b%d, type 0%o\n", LNPair(name), bstart, type);
++ DEBUG_ON(bstart < 0 || IS_ROOT(dentry));
++ parent = dget_parent(dentry);
++
++#if 1 //ndef CONFIG_AUFS_ROBR
++ err = -EPERM;
++ if (unlikely(!strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ goto out;
++#endif
++
++ err = au_alloc_whname(name->name, name->len, &whname);
++ //if (LktrCond) {au_free_whname(&whname); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ sb = dentry->d_sb;
++ dlgt = need_dlgt(sb);
++ allow_neg = !type;
++ npositive = 0;
++ btail = dbtaildir(parent);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ struct dentry *hidden_parent, *hidden_dentry;
++ struct inode *hidden_inode;
++ struct inode *hidden_dir;
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry) {
++ if (hidden_dentry->d_inode)
++ npositive++;
++ if (type != S_IFDIR)
++ break;
++ continue;
++ }
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ if (!hidden_parent)
++ continue;
++ hidden_dir = hidden_parent->d_inode;
++ if (!hidden_dir || !S_ISDIR(hidden_dir->i_mode))
++ continue;
++
++ hi_lock_parent(hidden_dir);
++ hidden_dentry = do_lookup(hidden_parent, dentry, bindex,
++ &whname, allow_neg, type, dlgt);
++ // do not dput for testing
++ //if (LktrCond) {hidden_dentry = ERR_PTR(-1);}
++ i_unlock(hidden_dir);
++ err = PTR_ERR(hidden_dentry);
++ if (IS_ERR(hidden_dentry))
++ goto out_wh;
++ allow_neg = 0;
++
++ if (dbwh(dentry) != -1)
++ break;
++ if (!hidden_dentry)
++ continue;
++ hidden_inode = hidden_dentry->d_inode;
++ if (!hidden_inode)
++ continue;
++ npositive++;
++ if (!type)
++ type = hidden_inode->i_mode & S_IFMT;
++ if (type != S_IFDIR)
++ break;
++ else if (dbdiropq(dentry) != -1)
++ break;
++ }
++
++ if (npositive) {
++ LKTRLabel(positive);
++ au_update_dbstart(dentry);
++ }
++ err = npositive;
++
++ out_wh:
++ au_free_whname(&whname);
++ out:
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ struct dentry *dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(parent), len, name);
++ IMustLock(parent->d_inode);
++
++ if (!au_test_perm(parent->d_inode, MAY_EXEC, lkup->dlgt))
++ dentry = lkup_one(name, parent, len, lkup);
++ else {
++ // ugly
++ int dlgt = lkup->dlgt;
++ struct lkup_one_args args = {
++ .errp = &dentry,
++ .name = name,
++ .parent = parent,
++ .len = len,
++ .lkup = lkup
++ };
++
++ lkup->dlgt = 0;
++ au_wkq_wait(call_lkup_one, &args, /*dlgt*/0);
++ lkup->dlgt = dlgt;
++ }
++
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/*
++ * lookup @dentry on @bindex which should be negative.
++ */
++int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct dentry *parent, *hidden_parent, *hidden_dentry;
++ struct inode *hidden_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++ parent = dget_parent(dentry);
++ DEBUG_ON(!parent || !parent->d_inode
++ || !S_ISDIR(parent->d_inode->i_mode));
++ hidden_parent = au_h_dptr_i(parent, bindex);
++ DEBUG_ON(!hidden_parent);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bindex);
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ hidden_dentry = sio_lkup_one(dentry->d_name.name, hidden_parent,
++ dentry->d_name.len, &lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(hidden_dentry);
++ if (IS_ERR(hidden_dentry))
++ goto out;
++ if (unlikely(hidden_dentry->d_inode)) {
++ err = -EIO;
++ IOErr("b%d %.*s should be negative.%s\n",
++ bindex, DLNPair(hidden_dentry),
++ au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY) ? "" :
++ " Try udba=inotify.");
++ dput(hidden_dentry);
++ goto out;
++ }
++
++ if (bindex < dbstart(dentry))
++ set_dbstart(dentry, bindex);
++ if (dbend(dentry) < bindex)
++ set_dbend(dentry, bindex);
++ set_h_dptr(dentry, bindex, hidden_dentry);
++ err = 0;
++
++ out:
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns the number of found hidden positive dentries,
++ * otherwise an error.
++ */
++int au_refresh_hdentry(struct dentry *dentry, mode_t type)
++{
++ int npositive, pgen, new_sz, sgen, dgen;
++ struct aufs_dinfo *dinfo;
++ struct super_block *sb;
++ struct dentry *parent;
++ aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
++ struct aufs_hdentry *p;
++ //struct nameidata nd;
++
++ LKTRTrace("%.*s, type 0%o\n", DLNPair(dentry), type);
++ DiMustWriteLock(dentry);
++ sb = dentry->d_sb;
++ DEBUG_ON(IS_ROOT(dentry));
++ parent = dget_parent(dentry);
++ pgen = au_digen(parent);
++ sgen = au_sigen(sb);
++ dgen = au_digen(dentry);
++ DEBUG_ON(pgen != sgen);
++
++ npositive = -ENOMEM;
++ new_sz = sizeof(*dinfo->di_hdentry) * (sbend(sb) + 1);
++ dinfo = dtodi(dentry);
++ p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++ dinfo->di_hdentry = p;
++
++ bend = dinfo->di_bend;
++ bwh = dinfo->di_bwh;
++ bdiropq = dinfo->di_bdiropq;
++ p += dinfo->di_bstart;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
++ struct dentry *hd, *hdp;
++ struct aufs_hdentry tmp, *q;
++ aufs_bindex_t new_bindex;
++
++ hd = p->hd_dentry;
++ if (!hd)
++ continue;
++ hdp = dget_parent(hd);
++ if (hdp == au_h_dptr_i(parent, bindex)) {
++ dput(hdp);
++ continue;
++ }
++
++ new_bindex = au_find_dbindex(parent, hdp);
++ dput(hdp);
++ DEBUG_ON(new_bindex == bindex);
++ if (dinfo->di_bwh == bindex)
++ bwh = new_bindex;
++ if (dinfo->di_bdiropq == bindex)
++ bdiropq = new_bindex;
++ if (new_bindex < 0) { // test here
++ hdput(p);
++ p->hd_dentry = NULL;
++ continue;
++ }
++ /* swap two hidden dentries, and loop again */
++ q = dinfo->di_hdentry + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hd_dentry) {
++ bindex--;
++ p--;
++ }
++ }
++
++ // test here
++ dinfo->di_bwh = -1;
++ if (unlikely(bwh != -1 && bwh <= sbend(sb) && sbr_is_whable(sb, bwh)))
++ dinfo->di_bwh = bwh;
++ dinfo->di_bdiropq = -1;
++ if (unlikely(bdiropq != -1 && bdiropq <= sbend(sb)
++ && sbr_is_whable(sb, bdiropq)))
++ dinfo->di_bdiropq = bdiropq;
++ parent_bend = dbend(parent);
++ p = dinfo->di_hdentry;
++ for (bindex = 0; bindex <= parent_bend; bindex++, p++)
++ if (p->hd_dentry) {
++ dinfo->di_bstart = bindex;
++ break;
++ }
++ p = dinfo->di_hdentry + parent_bend;
++ //for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
++ for (bindex = parent_bend; bindex >= 0; bindex--, p--)
++ if (p->hd_dentry) {
++ dinfo->di_bend = bindex;
++ break;
++ }
++
++ npositive = 0;
++ parent_bstart = dbstart(parent);
++ if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
++ goto out_dgen; /* success */
++
++#if 0
++ nd.last_type = LAST_ROOT;
++ nd.flags = LOOKUP_FOLLOW;
++ nd.depth = 0;
++ nd.mnt = mntget(??);
++ nd.dentry = dget(parent);
++#endif
++ npositive = lkup_dentry(dentry, parent_bstart, type);
++ //if (LktrCond) npositive = -1;
++ if (npositive < 0)
++ goto out;
++
++ out_dgen:
++ au_update_digen(dentry);
++ out:
++ dput(parent);
++ TraceErr(npositive);
++ return npositive;
++}
++
++static int h_d_revalidate(struct dentry *dentry, struct nameidata *nd,
++ int do_udba)
++{
++ int err, plus, locked, unhashed, is_root, h_plus, is_nfs;
++ struct nameidata fake_nd, *p;
++ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
++ struct super_block *sb;
++ struct inode *inode, *first, *h_inode, *h_cached_inode;
++ umode_t mode, h_mode;
++ struct dentry *h_dentry;
++ int (*reval)(struct dentry *, struct nameidata *);
++ struct qstr *name;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(inode && au_digen(dentry) != au_iigen(inode));
++ //DbgDentry(dentry);
++ //DbgInode(inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ plus = 0;
++ mode = 0;
++ first = NULL;
++ ibs = ibe = -1;
++ unhashed = d_unhashed(dentry);
++ is_root = IS_ROOT(dentry);
++ name = &dentry->d_name;
++
++ /*
++ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
++ * But inotify doesn't fire some necessary events,
++ * IN_ATTRIB for atime/nlink/pageio
++ * IN_DELETE for NFS dentry
++ * Let's do REVAL test too.
++ */
++ if (do_udba && inode) {
++ mode = (inode->i_mode & S_IFMT);
++ plus = (inode->i_nlink > 0);
++ first = au_h_iptr(inode);
++ ibs = ibstart(inode);
++ ibe = ibend(inode);
++ }
++
++ btail = bstart = dbstart(dentry);
++ if (inode && S_ISDIR(inode->i_mode))
++ btail = dbtaildir(dentry);
++ locked = 0;
++ if (nd) {
++ fake_nd = *nd;
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (dentry != nd->dentry) {
++ di_read_lock_parent(nd->dentry, 0);
++ locked = 1;
++ }
++#endif
++ }
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr_i(dentry, bindex);
++ if (unlikely(!h_dentry))
++ continue;
++ if (unlikely(do_udba
++ && !is_root
++ && (unhashed != d_unhashed(h_dentry)
++#if 1
++ || name->len != h_dentry->d_name.len
++ || memcmp(name->name, h_dentry->d_name.name,
++ name->len)
++#endif
++ ))) {
++ LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
++ unhashed, d_unhashed(h_dentry),
++ DLNPair(dentry), DLNPair(h_dentry));
++ goto err;
++ }
++
++ reval = NULL;
++ if (h_dentry->d_op)
++ reval = h_dentry->d_op->d_revalidate;
++ if (unlikely(reval)) {
++ //LKTRLabel(hidden reval);
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ DEBUG_ON(IS_ERR(p));
++ err = !reval(h_dentry, p);
++ fake_dm_release(p);
++ if (unlikely(err)) {
++ //Dbg("here\n");
++ goto err;
++ }
++ }
++
++ if (unlikely(!do_udba))
++ continue;
++
++ /* UDBA tests */
++ h_inode = h_dentry->d_inode;
++ if (unlikely(!!inode != !!h_inode)) {
++ //Dbg("here\n");
++ goto err;
++ }
++
++ h_plus = plus;
++ h_mode = mode;
++ h_cached_inode = h_inode;
++ is_nfs = 0;
++ if (h_inode) {
++ h_mode = (h_inode->i_mode & S_IFMT);
++ h_plus = (h_inode->i_nlink > 0);
++ }
++ if (inode && ibs <= bindex && bindex <= ibe) {
++ h_cached_inode = au_h_iptr_i(inode, bindex);
++ //is_nfs = au_is_nfs(h_cached_inode->i_sb);
++ }
++
++ LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
++ plus, mode, h_cached_inode,
++ h_plus, h_mode, h_inode);
++ if (unlikely(plus != h_plus || mode != h_mode
++ || (h_cached_inode != h_inode /* && !is_nfs */))) {
++ //Dbg("here\n");
++ goto err;
++ }
++ continue;
++
++ err:
++ err = -EINVAL;
++ break;
++ }
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (unlikely(locked))
++ di_read_unlock(nd->dentry, 0);
++#endif
++
++#if 0
++ // some filesystem uses CURRENT_TIME_SEC instead of CURRENT_TIME.
++ // NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
++#if 0
++ && (!timespec_equal(&inode->i_ctime, &first->i_ctime)
++ || !timespec_equal(&inode->i_atime, &first->i_atime))
++#endif
++ if (unlikely(!err && udba && first))
++ au_cpup_attr_all(inode);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++static int simple_reval_dpath(struct dentry *dentry, int sgen)
++{
++ int err;
++ mode_t type;
++ struct dentry *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
++ SiMustAnyLock(dentry->d_sb);
++ DiMustWriteLock(dentry);
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode);
++
++ if (au_digen(dentry) == sgen)
++ return 0;
++
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ DEBUG_ON(au_digen(parent) != sgen);
++#ifdef CONFIG_AUFS_DEBUG
++ {
++ struct dentry *d = parent;
++ while (!IS_ROOT(d)) {
++ DEBUG_ON(au_digen(d) != sgen);
++ d = d->d_parent;
++ }
++ }
++#endif
++ type = (inode->i_mode & S_IFMT);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, type);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, dentry);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ dput(parent);
++ TraceErr(err);
++ return err;
++}
++
++int au_reval_dpath(struct dentry *dentry, int sgen)
++{
++ int err;
++ struct dentry *d, *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
++ DEBUG_ON(!dentry->d_inode);
++ DiMustWriteLock(dentry);
++
++ if (!stosi(dentry->d_sb)->si_failed_refresh_dirs)
++ return simple_reval_dpath(dentry, sgen);
++
++ /* slow loop, keep it simple and stupid */
++ /* cf: cpup_dirs() */
++ err = 0;
++ while (au_digen(dentry) != sgen) {
++ d = dentry;
++ while (1) {
++ parent = d->d_parent; // dget_parent()
++ if (au_digen(parent) == sgen)
++ break;
++ d = parent;
++ }
++
++ inode = d->d_inode;
++ if (d != dentry) {
++ //i_lock(inode);
++ di_write_lock_child(d);
++ }
++
++ /* someone might update our dentry while we were sleeping */
++ if (au_digen(d) != sgen) {
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
++ //err = -1;
++ if (err >= 0)
++ err = au_refresh_hinode(inode, d);
++ //err = -1;
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++
++ if (d != dentry) {
++ di_write_unlock(d);
++ //i_unlock(inode);
++ }
++ if (unlikely(err))
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
++ * nfsd passes NULL as nameidata.
++ */
++static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
++{
++ int valid, sgen, err, do_udba;
++ struct super_block *sb;
++ struct inode *inode;
++
++ LKTRTrace("dentry %.*s\n", DLNPair(dentry));
++ if (nd && nd->dentry)
++ LKTRTrace("nd %.*s\n", DLNPair(nd->dentry));
++ //dir case: DEBUG_ON(dentry->d_parent != nd->dentry);
++ //remove failure case: DEBUG_ON(!IS_ROOT(dentry) && d_unhashed(dentry));
++ DEBUG_ON(!dentry->d_fsdata);
++ //DbgDentry(dentry);
++
++ err = -EINVAL;
++ inode = dentry->d_inode;
++ //DbgInode(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ sgen = au_sigen(sb);
++ if (au_digen(dentry) == sgen)
++ di_read_lock_child(dentry, !AUFS_I_RLOCK);
++ else {
++ DEBUG_ON(IS_ROOT(dentry));
++#ifdef ForceInotify
++ Dbg("UDBA or digen, %.*s\n", DLNPair(dentry));
++#endif
++ //i_lock(inode);
++ di_write_lock_child(dentry);
++ if (inode)
++ err = au_reval_dpath(dentry, sgen);
++ //err = -1;
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ //i_unlock(inode);
++ if (unlikely(err))
++ goto out;
++ ii_read_unlock(inode);
++ DEBUG_ON(au_iigen(inode) != sgen);
++ }
++
++ if (inode) {
++ if (au_iigen(inode) == sgen)
++ ii_read_lock_child(inode);
++ else {
++ DEBUG_ON(IS_ROOT(dentry));
++#ifdef ForceInotify
++ Dbg("UDBA or survived, %.*s\n", DLNPair(dentry));
++#endif
++ ii_write_lock_child(inode);
++ err = au_refresh_hinode(inode, dentry);
++ ii_downgrade_lock(inode);
++ if (unlikely(err))
++ goto out;
++ DEBUG_ON(au_iigen(inode) != sgen);
++ }
++ }
++
++#if 0 // fix it
++ /* parent dir i_nlink is not updated in the case of setattr */
++ if (S_ISDIR(inode->i_mode)) {
++ i_lock(inode);
++ ii_write_lock(inode);
++ au_cpup_attr_nlink(inode);
++ ii_write_unlock(inode);
++ i_unlock(inode);
++ }
++#endif
++
++ err = -EINVAL;
++ do_udba = !au_flag_test(sb, AuFlag_UDBA_NONE);
++ if (do_udba && inode && ibstart(inode) >= 0
++ && au_test_higen(inode, au_h_iptr(inode)))
++ goto out;
++ err = h_d_revalidate(dentry, nd, do_udba);
++ //err = -1;
++
++ out:
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ TraceErr(err);
++ valid = !err;
++ //au_debug_on();
++ if (!valid)
++ LKTRTrace("%.*s invalid\n", DLNPair(dentry));
++ //au_debug_off();
++ return valid;
++}
++
++static void aufs_d_release(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!d_unhashed(dentry));
++
++ dinfo = dentry->d_fsdata;
++ if (unlikely(!dinfo))
++ return;
++
++ /* dentry may not be revalidated */
++ bindex = dinfo->di_bstart;
++ if (bindex >= 0) {
++ struct aufs_hdentry *p;
++ bend = dinfo->di_bend;
++ DEBUG_ON(bend < bindex);
++ p = dinfo->di_hdentry + bindex;
++ while (bindex++ <= bend) {
++ if (p->hd_dentry)
++ hdput(p);
++ p++;
++ }
++ }
++ kfree(dinfo->di_hdentry);
++ cache_free_dinfo(dinfo);
++}
++
++#if 0
++/* it may be called at remount time, too */
++static void aufs_d_iput(struct dentry *dentry, struct inode *inode)
++{
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, i%lu\n", DLNPair(dentry), inode->i_ino);
++
++ sb = dentry->d_sb;
++#if 0
++ si_read_lock(sb);
++ if (unlikely(au_flag_test(sb, AuFlag_PLINK)
++ && au_is_plinked(sb, inode))) {
++ ii_write_lock(inode);
++ au_update_brange(inode, 1);
++ ii_write_unlock(inode);
++ }
++ si_read_unlock(sb);
++#endif
++ iput(inode);
++}
++#endif
++
++struct dentry_operations aufs_dop = {
++ .d_revalidate = aufs_d_revalidate,
++ .d_release = aufs_d_release
++ //.d_iput = aufs_d_iput
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dentry.h linux-2.6.22.1/fs/aufs/dentry.h
+--- linux-2.6.22.1.oorig/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dentry.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,183 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dentry.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DENTRY_H__
++#define __AUFS_DENTRY_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++
++struct aufs_hdentry {
++ struct dentry *hd_dentry;
++};
++
++struct aufs_dinfo {
++ atomic_t di_generation;
++
++ struct aufs_rwsem di_rwsem;
++ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
++ struct aufs_hdentry *di_hdentry;
++};
++
++struct lkup_args {
++ struct vfsmount *nfsmnt;
++ int dlgt;
++ //struct super_block *sb;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry.c */
++#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup);
++#else
++static inline
++struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup)
++{
++ return lookup_one_len(name, parent, len);
++}
++#endif
++
++extern struct dentry_operations aufs_dop;
++struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
++ struct lkup_args *lkup);
++int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type);
++int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
++int au_refresh_hdentry(struct dentry *dentry, mode_t type);
++int au_reval_dpath(struct dentry *dentry, int sgen);
++
++/* dinfo.c */
++int au_alloc_dinfo(struct dentry *dentry);
++struct aufs_dinfo *dtodi(struct dentry *dentry);
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
++void di_read_unlock(struct dentry *d, int flags);
++void di_downgrade_lock(struct dentry *d, int flags);
++void di_write_lock(struct dentry *d, unsigned int lsc);
++void di_write_unlock(struct dentry *d);
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++aufs_bindex_t dbstart(struct dentry *dentry);
++aufs_bindex_t dbend(struct dentry *dentry);
++aufs_bindex_t dbwh(struct dentry *dentry);
++aufs_bindex_t dbdiropq(struct dentry *dentry);
++struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex);
++struct dentry *au_h_dptr(struct dentry *dentry);
++
++aufs_bindex_t dbtail(struct dentry *dentry);
++aufs_bindex_t dbtaildir(struct dentry *dentry);
++aufs_bindex_t dbtail_generic(struct dentry *dentry);
++
++void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbend(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex);
++void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
++void hdput(struct aufs_hdentry *hdentry);
++void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++
++void au_update_digen(struct dentry *dentry);
++void au_update_dbstart(struct dentry *dentry);
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_digen(struct dentry *d)
++{
++ return atomic_read(&dtodi(d)->di_generation);
++}
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_digen_dec(struct dentry *d)
++{
++ atomic_dec(&dtodi(d)->di_generation);
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for dinfo */
++enum {
++ AuLsc_DI_CHILD, /* child first */
++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_DI_CHILD3, /* copyup dirs */
++ AuLsc_DI_PARENT,
++ AuLsc_DI_PARENT2,
++ AuLsc_DI_PARENT3
++};
++
++/*
++ * di_read_lock_child, di_write_lock_child,
++ * di_read_lock_child2, di_write_lock_child2,
++ * di_read_lock_child3, di_write_lock_child3,
++ * di_read_lock_parent, di_write_lock_parent,
++ * di_read_lock_parent2, di_write_lock_parent2,
++ * di_read_lock_parent3, di_write_lock_parent3,
++ */
++#define ReadLockFunc(name, lsc) \
++static inline void di_read_lock_##name(struct dentry *d, int flags) \
++{di_read_lock(d, flags, AuLsc_DI_##lsc);}
++
++#define WriteLockFunc(name, lsc) \
++static inline void di_write_lock_##name(struct dentry *d) \
++{di_write_lock(d, AuLsc_DI_##lsc);}
++
++#define RWLockFuncs(name, lsc) \
++ ReadLockFunc(name, lsc); \
++ WriteLockFunc(name, lsc)
++
++RWLockFuncs(child, CHILD);
++RWLockFuncs(child2, CHILD2);
++RWLockFuncs(child3, CHILD3);
++RWLockFuncs(parent, PARENT);
++RWLockFuncs(parent2, PARENT2);
++RWLockFuncs(parent3, PARENT3);
++
++#undef ReadLockFunc
++#undef WriteLockFunc
++#undef RWLockFunc
++
++/* to debug easier, do not make them inlined functions */
++#define DiMustReadLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustReadLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustWriteLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustWriteLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustAnyLock(d) do { \
++ SiMustAnyLock((d)->d_sb); \
++ RwMustAnyLock(&dtodi(d)->di_rwsem); \
++} while (0)
++
++#define DiMustNoWaiters(d) RwMustNoWaiters(&dtodi(d)->di_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DENTRY_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dinfo.c linux-2.6.22.1/fs/aufs/dinfo.c
+--- linux-2.6.22.1.oorig/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dinfo.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,419 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dinfo.c,v 1.23 2007/05/07 03:43:36 sfjro Exp $ */
++
++#include "aufs.h"
++
++int au_alloc_dinfo(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo;
++ struct super_block *sb;
++ int nbr;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(dentry->d_fsdata);
++
++ dinfo = cache_alloc_dinfo();
++ //if (LktrCond) {cache_free_dinfo(dinfo); dinfo = NULL;}
++ if (dinfo) {
++ sb = dentry->d_sb;
++ nbr = sbend(sb) + 1;
++ if (unlikely(!nbr))
++ nbr++;
++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
++ GFP_KERNEL);
++ //if (LktrCond)
++ //{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
++ if (dinfo->di_hdentry) {
++ rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
++ dinfo->di_bstart = dinfo->di_bend = -1;
++ dinfo->di_bwh = dinfo->di_bdiropq = -1;
++ atomic_set(&dinfo->di_generation, au_sigen(sb));
++
++ dentry->d_fsdata = dinfo;
++ dentry->d_op = &aufs_dop;
++ return 0; /* success */
++ }
++ cache_free_dinfo(dinfo);
++ }
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
++
++struct aufs_dinfo *dtodi(struct dentry *dentry)
++{
++ struct aufs_dinfo *dinfo = dentry->d_fsdata;
++ DEBUG_ON(!dinfo
++ || !dinfo->di_hdentry
++ /* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
++ || dinfo->di_bend < dinfo->di_bstart
++ /* dbwh can be outside of this range */
++ || (0 <= dinfo->di_bdiropq
++ && (dinfo->di_bdiropq < dinfo->di_bstart
++ /* || dinfo->di_bend < dinfo->di_bdiropq */))
++ );
++ return dinfo;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_write_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_write_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_write_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_write_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_write_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_write_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_read_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_read_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_read_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_read_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_read_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_read_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
++{
++ SiMustAnyLock(d->d_sb);
++ // todo: always nested?
++ rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
++ if (d->d_inode) {
++ if (flags & AUFS_I_WLOCK)
++ do_ii_write_lock(d->d_inode, lsc);
++ else if (flags & AUFS_I_RLOCK)
++ do_ii_read_lock(d->d_inode, lsc);
++ }
++}
++
++void di_read_unlock(struct dentry *d, int flags)
++{
++ SiMustAnyLock(d->d_sb);
++ if (d->d_inode) {
++ if (flags & AUFS_I_WLOCK)
++ ii_write_unlock(d->d_inode);
++ else if (flags & AUFS_I_RLOCK)
++ ii_read_unlock(d->d_inode);
++ }
++ rw_read_unlock(&dtodi(d)->di_rwsem);
++}
++
++void di_downgrade_lock(struct dentry *d, int flags)
++{
++ SiMustAnyLock(d->d_sb);
++ rw_dgrade_lock(&dtodi(d)->di_rwsem);
++ if (d->d_inode && (flags & AUFS_I_RLOCK))
++ ii_downgrade_lock(d->d_inode);
++}
++
++void di_write_lock(struct dentry *d, unsigned int lsc)
++{
++ SiMustAnyLock(d->d_sb);
++ // todo: always nested?
++ rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
++ if (d->d_inode)
++ do_ii_write_lock(d->d_inode, lsc);
++}
++
++void di_write_unlock(struct dentry *d)
++{
++ SiMustAnyLock(d->d_sb);
++ if (d->d_inode)
++ ii_write_unlock(d->d_inode);
++ rw_write_unlock(&dtodi(d)->di_rwsem);
++}
++
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ struct dentry *d;
++
++ TraceEnter();
++ DEBUG_ON(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir)
++ for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
++ if (d->d_parent == d2) {
++ di_write_lock_child(d1);
++ di_write_lock_child2(d2);
++ return;
++ }
++
++ di_write_lock_child(d2);
++ di_write_lock_child2(d1);
++}
++
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ struct dentry *d;
++
++ TraceEnter();
++ DEBUG_ON(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir)
++ for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
++ if (d->d_parent == d2) {
++ di_write_lock_parent(d1);
++ di_write_lock_parent2(d2);
++ return;
++ }
++
++ di_write_lock_parent(d2);
++ di_write_lock_parent2(d1);
++}
++
++void di_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock(d1);
++ if (d1->d_inode == d2->d_inode)
++ rw_write_unlock(&dtodi(d2)->di_rwsem);
++ else
++ di_write_unlock(d2);
++}
++
++/* ---------------------------------------------------------------------- */
++
++aufs_bindex_t dbstart(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bstart;
++}
++
++aufs_bindex_t dbend(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bend;
++}
++
++aufs_bindex_t dbwh(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ return dtodi(dentry)->di_bwh;
++}
++
++aufs_bindex_t dbdiropq(struct dentry *dentry)
++{
++ DiMustAnyLock(dentry);
++ DEBUG_ON(dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode));
++ return dtodi(dentry)->di_bdiropq;
++}
++
++struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ struct dentry *d;
++
++ DiMustAnyLock(dentry);
++ if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
++ return NULL;
++ DEBUG_ON(bindex < 0
++ /* || bindex > sbend(dentry->d_sb) */);
++ d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
++ DEBUG_ON(d && (atomic_read(&d->d_count) <= 0));
++ return d;
++}
++
++struct dentry *au_h_dptr(struct dentry *dentry)
++{
++ return au_h_dptr_i(dentry, dbstart(dentry));
++}
++
++aufs_bindex_t dbtail(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bwh;
++
++ bend = dbend(dentry);
++ if (0 <= bend) {
++ bwh = dbwh(dentry);
++ //DEBUG_ON(bend < bwh);
++ if (!bwh)
++ return bwh;
++ if (0 < bwh && bwh < bend)
++ return bwh - 1;
++ }
++ return bend;
++}
++
++aufs_bindex_t dbtaildir(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bopq;
++
++ DEBUG_ON(dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode));
++
++ bend = dbtail(dentry);
++ if (0 <= bend) {
++ bopq = dbdiropq(dentry);
++ DEBUG_ON(bend < bopq);
++ if (0 <= bopq && bopq < bend)
++ bend = bopq;
++ }
++ return bend;
++}
++
++aufs_bindex_t dbtail_generic(struct dentry *dentry)
++{
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (inode && S_ISDIR(inode->i_mode))
++ return dbtaildir(dentry);
++ else
++ return dbtail(dentry);
++}
++
++/* ---------------------------------------------------------------------- */
++
++// hard/soft set
++void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ /* */
++ dtodi(dentry)->di_bstart = bindex;
++}
++
++void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex
++ || bindex < dbstart(dentry));
++ dtodi(dentry)->di_bend = bindex;
++}
++
++void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ /* dbwh can be outside of bstart - bend range */
++ dtodi(dentry)->di_bwh = bindex;
++}
++
++void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ DiMustWriteLock(dentry);
++ DEBUG_ON(sbend(dentry->d_sb) < bindex);
++ DEBUG_ON((bindex != -1
++ && (bindex < dbstart(dentry) || dbend(dentry) < bindex))
++ || (dentry->d_inode
++ && dentry->d_inode->i_mode
++ && !S_ISDIR(dentry->d_inode->i_mode)));
++ dtodi(dentry)->di_bdiropq = bindex;
++}
++
++void hdput(struct aufs_hdentry *hd)
++{
++ dput(hd->hd_dentry);
++}
++
++void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
++ DiMustWriteLock(dentry);
++ DEBUG_ON(bindex < dtodi(dentry)->di_bstart
++ || bindex > dtodi(dentry)->di_bend
++ || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
++ || (h_dentry && hd->hd_dentry)
++ );
++ if (hd->hd_dentry)
++ hdput(hd);
++ hd->hd_dentry = h_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_update_digen(struct dentry *dentry)
++{
++ //DiMustWriteLock(dentry);
++ DEBUG_ON(!dentry->d_sb);
++ atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
++}
++
++void au_update_dbstart(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
++ struct dentry *hidden_dentry;
++
++ DiMustWriteLock(dentry);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ if (hidden_dentry->d_inode) {
++ set_dbstart(dentry, bindex);
++ return;
++ }
++ set_h_dptr(dentry, bindex, NULL);
++ }
++ //set_dbstart(dentry, -1);
++ //set_dbend(dentry, -1);
++}
++
++int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++)
++ if (au_h_dptr_i(dentry, bindex) == hidden_dentry)
++ return bindex;
++ return -1;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dir.c linux-2.6.22.1/fs/aufs/dir.c
+--- linux-2.6.22.1.oorig/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dir.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,564 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dir.c,v 1.36 2007/05/14 03:38:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static int reopen_dir(struct file *file)
++{
++ int err;
++ struct dentry *dentry, *hidden_dentry;
++ aufs_bindex_t bindex, btail, bstart;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++
++ /* open all hidden dirs */
++ bstart = dbstart(dentry);
++#if 1
++ for (bindex = fbstart(file); bindex < bstart; bindex++)
++ set_h_fptr(file, bindex, NULL);
++#endif
++ set_fbstart(file, bstart);
++ btail = dbtaildir(dentry);
++#if 1
++ for (bindex = fbend(file); btail < bindex; bindex--)
++ set_h_fptr(file, bindex, NULL);
++#endif
++ set_fbend(file, btail);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (hidden_file) {
++ DEBUG_ON(hidden_file->f_dentry != hidden_dentry);
++ continue;
++ }
++
++ hidden_file = hidden_open(dentry, bindex, file->f_flags);
++ // unavailable
++ //if (LktrCond) {fput(hidden_file);
++ //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out; // close all?
++ //cpup_file_flags(hidden_file, file);
++ set_h_fptr(file, bindex, hidden_file);
++ }
++ err = 0;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int do_open_dir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex, btail;
++ struct dentry *dentry, *hidden_dentry;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, 0x%x\n", DLNPair(dentry), flags);
++ DEBUG_ON(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
++
++ err = 0;
++ set_fvdir_cache(file, NULL);
++ file->f_version = dentry->d_inode->i_version;
++ bindex = dbstart(dentry);
++ set_fbstart(file, bindex);
++ btail = dbtaildir(dentry);
++ set_fbend(file, btail);
++ for (; !err && bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++
++ hidden_file = hidden_open(dentry, bindex, flags);
++ //if (LktrCond) {fput(hidden_file);
++ //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
++ if (!IS_ERR(hidden_file)) {
++ set_h_fptr(file, bindex, hidden_file);
++ continue;
++ }
++ err = PTR_ERR(hidden_file);
++ }
++ if (!err)
++ return 0; /* success */
++
++ /* close all */
++ for (bindex = fbstart(file); !err && bindex <= btail; bindex++)
++ set_h_fptr(file, bindex, NULL);
++ set_fbstart(file, -1);
++ set_fbend(file, -1);
++ return err;
++}
++
++static int aufs_open_dir(struct inode *inode, struct file *file)
++{
++ return au_do_open(inode, file, do_open_dir);
++}
++
++static int aufs_release_dir(struct inode *inode, struct file *file)
++{
++ struct aufs_vdir *vdir_cache;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
++
++ sb = file->f_dentry->d_sb;
++ si_read_lock(sb);
++ fi_write_lock(file);
++ vdir_cache = fvdir_cache(file);
++ if (vdir_cache)
++ free_vdir(vdir_cache);
++ fi_write_unlock(file);
++ au_fin_finfo(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++static int fsync_dir(struct dentry *dentry, int datasync)
++{
++ int err;
++ struct inode *inode;
++ struct super_block *sb;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ DiMustAnyLock(dentry);
++ sb = dentry->d_sb;
++ SiMustAnyLock(sb);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ IiMustAnyLock(inode);
++
++ err = 0;
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); !err && bindex <= bend; bindex++) {
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct file_operations *fop;
++
++ if (test_ro(sb, bindex, inode))
++ continue;
++ h_dentry = au_h_dptr_i(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ h_inode = h_dentry->d_inode;
++ if (!h_inode)
++ continue;
++
++ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
++ //hdir_lock(h_inode, inode, bindex);
++ i_lock(h_inode);
++ fop = (void*)h_inode->i_fop;
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ if (!err && fop && fop->fsync)
++ err = fop->fsync(NULL, h_dentry, datasync);
++ if (!err)
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ //hdir_unlock(h_inode, inode, bindex);
++ i_unlock(h_inode);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * @file may be NULL
++ */
++static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct inode *inode;
++ struct file *hidden_file;
++ struct super_block *sb;
++ aufs_bindex_t bend, bindex;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ if (file) {
++ err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
++ /*locked*/1);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ } else
++ di_read_lock_child(dentry, !AUFS_I_WLOCK);
++
++ ii_write_lock_child(inode);
++ if (file) {
++ bend = fbend(file);
++ for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (!hidden_file || test_ro(sb, bindex, inode))
++ continue;
++
++ err = -EINVAL;
++ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++ // todo: try do_fsync() in fs/sync.c
++#if 0
++ DEBUG_ON(hidden_file->f_dentry->d_inode
++ != au_h_iptr_i(inode, bindex));
++ hdir_lock(hidden_file->f_dentry->d_inode, inode,
++ bindex);
++#else
++ i_lock(hidden_file->f_dentry->d_inode);
++#endif
++ err = hidden_file->f_op->fsync
++ (hidden_file, hidden_file->f_dentry,
++ datasync);
++ //err = -1;
++#if 0
++ hdir_unlock(hidden_file->f_dentry->d_inode,
++ inode, bindex);
++#else
++ i_unlock(hidden_file->f_dentry->d_inode);
++#endif
++ }
++ }
++ } else
++ err = fsync_dir(dentry, datasync);
++ au_cpup_attr_timesizes(inode);
++ ii_write_unlock(inode);
++ if (file)
++ fi_write_unlock(file);
++ else
++ di_read_unlock(dentry, !AUFS_I_WLOCK);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ au_nfsd_lockdep_off();
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
++ /*locked*/1);
++ if (unlikely(err))
++ goto out;
++
++ ii_write_lock_child(inode);
++ err = au_init_vdir(file);
++ if (unlikely(err)) {
++ ii_write_unlock(inode);
++ goto out_unlock;
++ }
++ //DbgVdir(fvdir_cache(file));// goto out_unlock;
++
++ /* nfsd filldir calls lookup_one_len(). */
++ ii_downgrade_lock(inode);
++ err = au_fill_de(file, dirent, filldir);
++ //DbgVdir(fvdir_cache(file));// goto out_unlock;
++
++ inode->i_atime = au_h_iptr(inode)->i_atime;
++ ii_read_unlock(inode);
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ au_nfsd_lockdep_on();
++#if 0 // debug
++ if (LktrCond)
++ igrab(inode);
++#endif
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct test_empty_arg {
++ struct aufs_nhash *whlist;
++ int whonly;
++ aufs_bindex_t bindex;
++ int err, called;
++};
++
++static int test_empty_cb(void *__arg, const char *__name, int namelen,
++ loff_t offset, filldir_ino_t ino, unsigned int d_type)
++{
++ struct test_empty_arg *arg = __arg;
++ char *name = (void*)__name;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ arg->err = 0;
++ arg->called++;
++ //smp_mb();
++ if (name[0] == '.'
++ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
++ return 0; /* success */
++
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (arg->whonly && !test_known_wh(arg->whlist, name, namelen))
++ arg->err = -ENOTEMPTY;
++ goto out;
++ }
++
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ if (!test_known_wh(arg->whlist, name, namelen))
++ arg->err = append_wh(arg->whlist, name, namelen, arg->bindex);
++
++ out:
++ //smp_mb();
++ TraceErr(arg->err);
++ return arg->err;
++}
++
++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err, dlgt;
++ struct file *hidden_file;
++
++ LKTRTrace("%.*s, {%p, %d, %d}\n",
++ DLNPair(dentry), arg->whlist, arg->whonly, arg->bindex);
++
++ hidden_file = hidden_open(dentry, arg->bindex,
++ O_RDONLY | O_NONBLOCK | O_DIRECTORY
++ | O_LARGEFILE);
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out;
++
++ dlgt = need_dlgt(dentry->d_sb);
++ //hidden_file->f_pos = 0;
++ do {
++ arg->err = 0;
++ arg->called = 0;
++ //smp_mb();
++ err = vfsub_readdir(hidden_file, test_empty_cb, arg, dlgt);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && arg->called);
++ fput(hidden_file);
++ sbr_put(dentry->d_sb, arg->bindex);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct do_test_empty_args {
++ int *errp;
++ struct dentry *dentry;
++ struct test_empty_arg *arg;
++};
++
++static void call_do_test_empty(void *args)
++{
++ struct do_test_empty_args *a = args;
++ *a->errp = do_test_empty(a->dentry, a->arg);
++}
++
++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err;
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ hidden_dentry = au_h_dptr_i(dentry, arg->bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode || !S_ISDIR(hidden_inode->i_mode));
++
++ hi_lock_child(hidden_inode);
++ err = au_test_perm(hidden_inode, MAY_EXEC | MAY_READ,
++ need_dlgt(dentry->d_sb));
++ i_unlock(hidden_inode);
++ if (!err)
++ err = do_test_empty(dentry, arg);
++ else {
++ struct do_test_empty_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .arg = arg
++ };
++ au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++int au_test_empty_lower(struct dentry *dentry)
++{
++ int err;
++ struct inode *inode;
++ struct test_empty_arg arg;
++ struct aufs_nhash *whlist;
++ aufs_bindex_t bindex, bstart, btail;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++
++ bstart = dbstart(dentry);
++ arg.whlist = whlist;
++ arg.whonly = 0;
++ arg.bindex = bstart;
++ err = do_test_empty(dentry, &arg);
++ if (unlikely(err))
++ goto out_whlist;
++
++ arg.whonly = 1;
++ btail = dbtaildir(dentry);
++ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
++ struct dentry *hidden_dentry;
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry && hidden_dentry->d_inode) {
++ DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
++ arg.bindex = bindex;
++ err = do_test_empty(dentry, &arg);
++ }
++ }
++
++ out_whlist:
++ nhash_del(whlist);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int test_empty(struct dentry *dentry, struct aufs_nhash *whlist)
++{
++ int err;
++ struct inode *inode;
++ struct test_empty_arg arg;
++ aufs_bindex_t bindex, btail;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ err = 0;
++ arg.whlist = whlist;
++ arg.whonly = 1;
++ btail = dbtaildir(dentry);
++ for (bindex = dbstart(dentry); !err && bindex <= btail; bindex++) {
++ struct dentry *hidden_dentry;
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (hidden_dentry && hidden_dentry->d_inode) {
++ DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
++ arg.bindex = bindex;
++ err = sio_test_empty(dentry, &arg);
++ }
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_add_nlink(struct inode *dir, struct inode *h_dir)
++{
++ DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++ dir->i_nlink += h_dir->i_nlink - 2;
++ if (unlikely(h_dir->i_nlink < 2))
++ dir->i_nlink += 2;
++}
++
++void au_sub_nlink(struct inode *dir, struct inode *h_dir)
++{
++ DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++ dir->i_nlink -= h_dir->i_nlink - 2;
++ if (unlikely(h_dir->i_nlink < 2))
++ dir->i_nlink -= 2;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 // comment
++struct file_operations {
++ struct module *owner;
++ loff_t (*llseek) (struct file *, loff_t, int);
++ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
++ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
++ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
++ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
++ int (*readdir) (struct file *, void *, filldir_t);
++ unsigned int (*poll) (struct file *, struct poll_table_struct *);
++ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
++ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
++ long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
++ int (*mmap) (struct file *, struct vm_area_struct *);
++ int (*open) (struct inode *, struct file *);
++ int (*flush) (struct file *);
++ int (*release) (struct inode *, struct file *);
++ int (*fsync) (struct file *, struct dentry *, int datasync);
++ int (*aio_fsync) (struct kiocb *, int datasync);
++ int (*fasync) (int, struct file *, int);
++ int (*lock) (struct file *, int, struct file_lock *);
++ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
++ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
++ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
++ int (*check_flags)(int);
++ int (*dir_notify)(struct file *file, unsigned long arg);
++ int (*flock) (struct file *, int, struct file_lock *);
++};
++#endif
++
++struct file_operations aufs_dir_fop = {
++ .read = generic_read_dir,
++ .readdir = aufs_readdir,
++ .open = aufs_open_dir,
++ .release = aufs_release_dir,
++ .flush = aufs_flush,
++ .fsync = aufs_fsync_dir,
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dir.h linux-2.6.22.1/fs/aufs/dir.h
+--- linux-2.6.22.1.oorig/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/dir.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,125 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: dir.h,v 1.18 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_DIR_H__
++#define __AUFS_DIR_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++#define filldir_ino_t u64
++#else
++#define filldir_ino_t ino_t
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* need to be faster and smaller */
++
++#define AUFS_DEBLK_SIZE 512 // todo: changable
++#define AUFS_NHASH_SIZE 32 // todo: changable
++#if AUFS_DEBLK_SIZE < NAME_MAX || PAGE_SIZE < AUFS_DEBLK_SIZE
++#error invalid size AUFS_DEBLK_SIZE
++#endif
++
++typedef char aufs_deblk_t[AUFS_DEBLK_SIZE];
++
++struct aufs_nhash {
++ struct hlist_head heads[AUFS_NHASH_SIZE];
++};
++
++struct aufs_destr {
++ unsigned char len;
++ char name[0];
++} __attribute__ ((packed));
++
++struct aufs_dehstr {
++ struct hlist_node hash;
++ struct aufs_destr *str;
++};
++
++struct aufs_de {
++ ino_t de_ino;
++ unsigned char de_type;
++ //caution: packed
++ struct aufs_destr de_str;
++} __attribute__ ((packed));
++
++struct aufs_wh {
++ struct hlist_node wh_hash;
++ aufs_bindex_t wh_bindex;
++ struct aufs_destr wh_str;
++} __attribute__ ((packed));
++
++union aufs_deblk_p {
++ unsigned char *p;
++ aufs_deblk_t *deblk;
++ struct aufs_de *de;
++};
++
++struct aufs_vdir {
++ aufs_deblk_t **vd_deblk;
++ int vd_nblk;
++ struct {
++ int i;
++ union aufs_deblk_p p;
++ } vd_last;
++
++ unsigned long vd_version;
++ unsigned long vd_jiffy;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dir.c */
++extern struct file_operations aufs_dir_fop;
++int au_test_empty_lower(struct dentry *dentry);
++int test_empty(struct dentry *dentry, struct aufs_nhash *whlist);
++void au_add_nlink(struct inode *dir, struct inode *h_dir);
++void au_sub_nlink(struct inode *dir, struct inode *h_dir);
++
++/* vdir.c */
++struct aufs_nhash *nhash_new(gfp_t gfp);
++void nhash_del(struct aufs_nhash *nhash);
++void nhash_init(struct aufs_nhash *nhash);
++void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src);
++void nhash_fin(struct aufs_nhash *nhash);
++int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit);
++int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen);
++int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
++ aufs_bindex_t bindex);
++void free_vdir(struct aufs_vdir *vdir);
++int au_init_vdir(struct file *file);
++int au_fill_de(struct file *file, void *dirent, filldir_t filldir);
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++unsigned int au_name_hash(const unsigned char *name, unsigned int len)
++{
++ return (full_name_hash(name, len) % AUFS_NHASH_SIZE);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DIR_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/export.c linux-2.6.22.1/fs/aufs/export.c
+--- linux-2.6.22.1.oorig/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/export.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,585 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: export.c,v 1.7 2007/05/14 03:38:24 sfjro Exp $ */
++
++#include "aufs.h"
++
++extern struct export_operations export_op_default;
++#define CALL(ops, func) (((ops)->func) ? ((ops)->func) : export_op_default.func)
++#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED)
++
++union conv {
++#if BITS_PER_LONG == 32
++ __u32 a[1];
++#else
++ __u32 a[2];
++#endif
++ ino_t ino;
++};
++
++static ino_t decode_ino(__u32 *a)
++{
++ union conv u;
++ u.a[0] = a[0];
++#if BITS_PER_LONG == 64
++ u.a[1] = a[1];
++#endif
++ return u.ino;
++}
++
++static void encode_ino(__u32 *a, ino_t ino)
++{
++ union conv u;
++ u.ino = ino;
++ a[0] = u.a[0];
++#if BITS_PER_LONG == 64
++ a[1] = u.a[1];
++#endif
++}
++
++static void decode_br_id_sigen(__u32 a, aufs_bindex_t *br_id,
++ aufs_bindex_t *sigen)
++{
++ BUILD_BUG_ON((sizeof(*br_id) + sizeof(*sigen)) > sizeof(a));
++ *br_id = a >> 16;
++ DEBUG_ON(*br_id < 0);
++ *sigen = a;
++ DEBUG_ON(*sigen < 0);
++}
++
++static __u32 encode_br_id_sigen(aufs_bindex_t br_id, aufs_bindex_t sigen)
++{
++ DEBUG_ON(br_id < 0 || sigen < 0);
++ return (br_id << 16) | sigen;
++}
++
++/* NFS file handle */
++enum {
++ /* support 64bit inode number */
++ /* but untested */
++ Fh_br_id_sigen,
++ Fh_ino1,
++#if BITS_PER_LONG == 64
++ Fh_ino2,
++#endif
++ Fh_dir_ino1,
++#if BITS_PER_LONG == 64
++ Fh_dir_ino2,
++#endif
++ Fh_h_ino1,
++#if BITS_PER_LONG == 64
++ Fh_h_ino2,
++#endif
++ Fh_h_igen,
++ Fh_h_type,
++ Fh_tail,
++
++ Fh_ino = Fh_ino1,
++ Fh_dir_ino = Fh_dir_ino1,
++ Fh_h_ino = Fh_h_ino1,
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry;
++ struct inode *inode;
++
++ LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
++
++ dentry = NULL;
++ inode = ilookup(sb, ino);
++ if (unlikely(!inode))
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ dentry = NULL;
++ if (!S_ISDIR(inode->i_mode)) {
++ struct dentry *d;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias)
++ if (!is_anon(d)
++ && d->d_parent->d_inode->i_ino == dir_ino) {
++ dentry = dget_locked(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ } else {
++ dentry = d_find_alias(inode);
++ if (dentry
++ && !is_anon(dentry)
++ && dentry->d_parent->d_inode->i_ino == dir_ino)
++ goto out_iput; /* success */
++
++ dput(dentry);
++ dentry = NULL;
++ }
++
++ out_iput:
++ iput(inode);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct find_name_by_ino {
++ int called, found;
++ ino_t ino;
++ char *name;
++ int namelen;
++};
++
++static int
++find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
++ filldir_ino_t ino, unsigned int d_type)
++{
++ struct find_name_by_ino *a = arg;
++
++ a->called++;
++ if (a->ino != ino)
++ return 0;
++
++ memcpy(a->name, name, namelen);
++ a->namelen = namelen;
++ a->found = 1;
++ return 1;
++}
++
++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry, *parent;
++ struct inode *dir;
++ struct find_name_by_ino arg;
++ struct file *file;
++ int err;
++
++ LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
++
++ dentry = NULL;
++ dir = ilookup(sb, dir_ino);
++ if (unlikely(!dir))
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ if (unlikely(is_bad_inode(dir)))
++ goto out_iput;
++
++ dentry = NULL;
++ parent = d_find_alias(dir);
++ if (parent) {
++ if (unlikely(is_anon(parent))) {
++ dput(parent);
++ goto out_iput;
++ }
++ } else
++ goto out_iput;
++
++ file = dentry_open(parent, NULL, au_dir_roflags);
++ dentry = (void*)file;
++ if (IS_ERR(file))
++ goto out_iput;
++
++ dentry = ERR_PTR(-ENOMEM);
++ arg.name = __getname();
++ if (unlikely(!arg.name))
++ goto out_fput;
++ arg.ino = ino;
++ arg.found = 0;
++
++ do {
++ arg.called = 0;
++ //smp_mb();
++ err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
++ } while (!err && !arg.found && arg.called);
++ dentry = ERR_PTR(err);
++ if (arg.found) {
++ /* do not call lkup_one(), nor dlgt */
++ i_lock(dir);
++ dentry = lookup_one_len(arg.name, parent, arg.namelen);
++ i_unlock(dir);
++ TraceErrPtr(dentry);
++ }
++
++ //out_putname:
++ __putname(arg.name);
++ out_fput:
++ fput(file);
++ out_iput:
++ iput(dir);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct append_name {
++ int found, called, len;
++ char *h_path;
++ ino_t h_ino;
++};
++
++static int append_name(void *arg, const char *name, int len, loff_t pos,
++ filldir_ino_t ino, unsigned int d_type)
++{
++ struct append_name *a = arg;
++ char *p;
++
++ a->called++;
++ if (ino != a->h_ino)
++ return 0;
++
++ DEBUG_ON(len == 1 && *name == '.');
++ DEBUG_ON(len == 2 && name[0] == '.' && name[1] == '.');
++ a->len = strlen(a->h_path);
++ memmove(a->h_path - a->len - 1, a->h_path, a->len);
++ a->h_path -= a->len + 1;
++ p = a->h_path + a->len;
++ *p++ = '/';
++ memcpy(p, name, a->len);
++ a->len += 1 + len;
++ a->found++;
++ return 1;
++}
++
++static int h_acceptable(void *expv, struct dentry *dentry)
++{
++ return 1;
++}
++
++static struct dentry*
++decode_by_path(struct super_block *sb, aufs_bindex_t bindex, __u32 *fh,
++ int fh_len, void *context)
++{
++ struct dentry *dentry, *h_parent, *root, *h_root;
++ struct super_block *h_sb;
++ char *path, *p;
++ struct vfsmount *h_mnt;
++ struct append_name arg;
++ int len, err;
++ struct file *h_file;
++ struct nameidata nd;
++ struct aufs_branch *br;
++
++ LKTRTrace("b%d\n", bindex);
++ SiMustAnyLock(sb);
++
++ br = stobr(sb, bindex);
++ //br_get(br);
++ h_mnt = br->br_mnt;
++ h_sb = h_mnt->mnt_sb;
++ LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
++ h_parent = CALL(h_sb->s_export_op, decode_fh)
++ (h_sb, fh + Fh_tail, fh_len - Fh_tail, fh[Fh_h_type],
++ h_acceptable, /*context*/NULL);
++ dentry = h_parent;
++ if (unlikely(!h_parent || IS_ERR(h_parent))) {
++ Warn1("%s decode_fh failed\n", au_sbtype(h_sb));
++ goto out;
++ }
++ dentry = NULL;
++ if (unlikely(is_anon(h_parent))) {
++ Warn1("%s decode_fh returned a disconnected dentry\n",
++ au_sbtype(h_sb));
++ dput(h_parent);
++ goto out;
++ }
++
++ dentry = ERR_PTR(-ENOMEM);
++ path = __getname();
++ if (unlikely(!path)) {
++ dput(h_parent);
++ goto out;
++ }
++
++ root = sb->s_root;
++ di_read_lock_parent(root, !AUFS_I_RLOCK);
++ h_root = au_h_dptr_i(root, bindex);
++ di_read_unlock(root, !AUFS_I_RLOCK);
++ arg.h_path = d_path(h_root, h_mnt, path, PATH_MAX);
++ dentry = (void*)arg.h_path;
++ if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
++ goto out_putname;
++ len = strlen(arg.h_path);
++ arg.h_path = d_path(h_parent, h_mnt, path, PATH_MAX);
++ dentry = (void*)arg.h_path;
++ if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
++ goto out_putname;
++ LKTRTrace("%s\n", arg.h_path);
++ if (len != 1)
++ arg.h_path += len;
++ LKTRTrace("%s\n", arg.h_path);
++
++ /* cf. fs/exportfs/expfs.c */
++ h_file = dentry_open(h_parent, NULL, au_dir_roflags);
++ dentry = (void*)h_file;
++ if (IS_ERR(h_file))
++ goto out_putname;
++
++ arg.found = 0;
++ arg.h_ino = decode_ino(fh + Fh_h_ino);
++ do {
++ arg.called = 0;
++ err = vfsub_readdir(h_file, append_name, &arg, /*dlgt*/0);
++ } while (!err && !arg.found && arg.called);
++ LKTRTrace("%s, %d\n", arg.h_path, arg.len);
++
++ p = d_path(root, stosi(sb)->si_mnt, path, PATH_MAX - arg.len - 2);
++ dentry = (void*)p;
++ if (unlikely(!p || IS_ERR(p)))
++ goto out_fput;
++ p[strlen(p)] = '/';
++ LKTRTrace("%s\n", p);
++
++ err = path_lookup(p, LOOKUP_FOLLOW, &nd);
++ dentry = ERR_PTR(err);
++ if (!err) {
++ dentry = dget(nd.dentry);
++ if (unlikely(is_anon(dentry))) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ path_release(&nd);
++ }
++
++ out_fput:
++ fput(h_file);
++ out_putname:
++ __putname(path);
++ out:
++ //br_put(br);
++ TraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry*
++aufs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context)
++{
++ struct dentry *dentry;
++ ino_t ino, dir_ino;
++ aufs_bindex_t bindex, br_id, sigen_v;
++ struct inode *inode, *h_inode;
++
++ //au_debug_on();
++ LKTRTrace("%d, fh{i%u, br_id_sigen 0x%x, hi%u}\n",
++ fh_type, fh[Fh_ino], fh[Fh_br_id_sigen], fh[Fh_h_ino]);
++ DEBUG_ON(fh_len < Fh_tail);
++
++ si_read_lock(sb);
++ lockdep_off();
++
++ /* branch id may be wrapped around */
++ dentry = ERR_PTR(-ESTALE);
++ decode_br_id_sigen(fh[Fh_br_id_sigen], &br_id, &sigen_v);
++ bindex = find_brindex(sb, br_id);
++ if (unlikely(bindex < 0 || au_sigen(sb) < sigen_v))
++ goto out;
++
++ /* is this inode still cached? */
++ ino = decode_ino(fh + Fh_ino);
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ dentry = decode_by_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out;
++ if (dentry)
++ goto accept;
++
++ /* is the parent dir cached? */
++ dentry = decode_by_dir_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out;
++ if (dentry)
++ goto accept;
++
++ /* lookup path */
++ dentry = decode_by_path(sb, bindex, fh, fh_len, context);
++ if (IS_ERR(dentry))
++ goto out;
++ if (unlikely(!dentry))
++ goto out_stale;
++ if (unlikely(dentry->d_inode->i_ino != ino))
++ goto out_dput;
++
++ accept:
++ inode = dentry->d_inode;
++ h_inode = NULL;
++ ii_read_lock_child(inode);
++ if (ibstart(inode) <= bindex && bindex <= ibend(inode))
++ h_inode = au_h_iptr_i(inode, bindex);
++ ii_read_unlock(inode);
++ if (h_inode
++ && h_inode->i_generation == fh[Fh_h_igen]
++ && acceptable(context, dentry))
++ goto out; /* success */
++ out_dput:
++ dput(dentry);
++ out_stale:
++ dentry = ERR_PTR(-ESTALE);
++ out:
++ lockdep_on();
++ si_read_unlock(sb);
++ TraceErrPtr(dentry);
++ //au_debug_off();
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
++ int connectable)
++{
++ int err;
++ struct super_block *sb, *h_sb;
++ struct inode *inode, *h_inode, *dir;
++ aufs_bindex_t bindex;
++ union conv u;
++ struct dentry *parent, *h_parent;
++
++ //au_debug_on();
++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
++ LKTRTrace("%.*s, max %d, conn %d\n",
++ DLNPair(dentry), *max_len, connectable);
++ DEBUG_ON(is_anon(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode);
++ parent = dentry->d_parent;
++ DEBUG_ON(is_anon(parent));
++
++ err = -ENOSPC;
++ if (unlikely(*max_len <= Fh_tail)) {
++ Warn1("NFSv2 client (max_len %d)?\n", *max_len);
++ goto out;
++ }
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++#ifdef CONFIG_AUFS_DEBUG
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ Warn1("NFS-exporting requires xino\n");
++#if 0
++ if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ Warn1("udba=inotify is not recommended when exporting\n");
++#endif
++#endif
++
++ err = -EPERM;
++ bindex = ibstart(inode);
++ h_sb = sbr_sb(sb, bindex);
++ if (unlikely(!h_sb->s_export_op)) {
++ Err1("%s branch is not exportable\n", au_sbtype(h_sb));
++ goto out_unlock;
++ }
++
++#if 0 //def CONFIG_AUFS_ROBR
++ if (unlikely(SB_AUFS(h_sb))) {
++ Err1("aufs branch is not supported\n");
++ goto out_unlock;
++ }
++#endif
++
++ /* doesn't support pseudo-link */
++ if (unlikely(bindex < dbstart(dentry)
++ || dbend(dentry) < bindex
++ || !au_h_dptr_i(dentry, bindex))) {
++ Err("%.*s/%.*s, b%d, pseudo-link?\n",
++ DLNPair(dentry->d_parent), DLNPair(dentry), bindex);
++ goto out_unlock;
++ }
++
++ fh[Fh_br_id_sigen] = encode_br_id_sigen(sbr_id(sb, bindex),
++ au_sigen(sb));
++ encode_ino(fh + Fh_ino, inode->i_ino);
++ dir = parent->d_inode;
++ encode_ino(fh + Fh_dir_ino, dir->i_ino);
++ h_inode = au_h_iptr(inode);
++ encode_ino(fh + Fh_h_ino, h_inode->i_ino);
++ fh[Fh_h_igen] = h_inode->i_generation;
++
++ /* it should be set at exporting time */
++ if (unlikely(!h_sb->s_export_op->find_exported_dentry)) {
++ Warn("set default find_exported_dentry for %s\n",
++ au_sbtype(h_sb));
++ h_sb->s_export_op->find_exported_dentry = find_exported_dentry;
++ }
++
++ *max_len -= Fh_tail;
++ //LKTRTrace("Fh_tail %d, max_len %d\n", Fh_tail, *max_len);
++ h_parent = au_h_dptr_i(parent, bindex);
++ DEBUG_ON(is_anon(h_parent));
++ err = fh[Fh_h_type] = CALL(h_sb->s_export_op, encode_fh)
++ (h_parent, fh + Fh_tail, max_len, connectable);
++ *max_len += Fh_tail;
++ if (err != 255)
++ err = 2; //??
++ else
++ Warn1("%s encode_fh failed\n", au_sbtype(h_sb));
++
++ out_unlock:
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ out:
++ TraceErr(err);
++ //au_debug_off();
++ if (unlikely(err < 0))
++ err = 255;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0
++struct export_operations {
++ struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context);
++ int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
++ int connectable);
++
++ /* the following are only called from the filesystem itself */
++ int (*get_name)(struct dentry *parent, char *name,
++ struct dentry *child);
++ struct dentry * (*get_parent)(struct dentry *child);
++ struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
++
++ /* This is set by the exporting module to a standard helper */
++ struct dentry * (*find_exported_dentry)(
++ struct super_block *sb, void *obj, void *parent,
++ int (*acceptable)(void *context, struct dentry *de),
++ void *context);
++};
++#endif
++
++struct export_operations aufs_export_op = {
++ .decode_fh = aufs_decode_fh,
++ .encode_fh = aufs_encode_fh
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/f_op.c linux-2.6.22.1/fs/aufs/f_op.c
+--- linux-2.6.22.1.oorig/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/f_op.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,684 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: f_op.c,v 1.27 2007/05/14 03:38:24 sfjro Exp $ */
++
++#include <linux/fsnotify.h>
++#include <linux/pagemap.h>
++#include <linux/poll.h>
++#include <linux/security.h>
++#include <linux/version.h>
++#include "aufs.h"
++
++/* common function to regular file and dir */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#define FlushArgs hidden_file, id
++int aufs_flush(struct file *file, fl_owner_t id)
++#else
++#define FlushArgs hidden_file
++int aufs_flush(struct file *file)
++#endif
++{
++ int err;
++ struct dentry *dentry;
++ aufs_bindex_t bindex, bend;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ // aufs_read_lock_file()
++ si_read_lock(dentry->d_sb);
++ fi_read_lock(file);
++ di_read_lock_child(dentry, !AUFS_I_RLOCK);
++
++ err = 0;
++ bend = fbend(file);
++ for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
++ struct file *hidden_file;
++ hidden_file = au_h_fptr_i(file, bindex);
++ if (hidden_file && hidden_file->f_op
++ && hidden_file->f_op->flush)
++ err = hidden_file->f_op->flush(FlushArgs);
++ }
++
++ di_read_unlock(dentry, !AUFS_I_RLOCK);
++ fi_read_unlock(file);
++ si_read_unlock(dentry->d_sb);
++ TraceErr(err);
++ return err;
++}
++#undef FlushArgs
++
++/* ---------------------------------------------------------------------- */
++
++static int do_open_nondir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct super_block *sb;
++ struct file *hidden_file;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_finfo *finfo;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, flags 0%o\n", DLNPair(dentry), flags);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || S_ISDIR(inode->i_mode));
++
++ err = 0;
++ finfo = ftofi(file);
++ finfo->fi_h_vm_ops = NULL;
++ sb = dentry->d_sb;
++ bindex = dbstart(dentry);
++ DEBUG_ON(!au_h_dptr(dentry)->d_inode);
++ /* O_TRUNC is processed already */
++ BUG_ON(test_ro(sb, bindex, inode) && (flags & O_TRUNC));
++
++ hidden_file = hidden_open(dentry, bindex, flags);
++ //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bindex));
++ //hidden_file = ERR_PTR(-1);}
++ if (!IS_ERR(hidden_file)) {
++ set_fbstart(file, bindex);
++ set_fbend(file, bindex);
++ set_h_fptr(file, bindex, hidden_file);
++ return 0; /* success */
++ }
++ err = PTR_ERR(hidden_file);
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_open_nondir(struct inode *inode, struct file *file)
++{
++ return au_do_open(inode, file, do_open_nondir);
++}
++
++static int aufs_release_nondir(struct inode *inode, struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
++
++ si_read_lock(sb);
++ au_fin_finfo(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct file *hidden_file;
++ struct super_block *sb;
++ struct inode *h_inode;
++ int dlgt;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(dentry), (unsigned long)count, *ppos);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //if (LktrCond) {fi_read_unlock(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ /* support LSM and notify */
++ dlgt = need_dlgt(sb);
++ hidden_file = au_h_fptr(file);
++ h_inode = hidden_file->f_dentry->d_inode;
++ if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
++ err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
++ else {
++ struct inode *dir = dentry->d_parent->d_inode,
++ *h_dir = hidden_file->f_dentry->d_parent->d_inode;
++ aufs_bindex_t bstart = fbstart(file);
++ hdir_lock(h_dir, dir, bstart);
++ err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
++ hdir_unlock(h_dir, dir, bstart);
++ }
++ memcpy(&file->f_ra, &hidden_file->f_ra, sizeof(file->f_ra)); //??
++ dentry->d_inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
++
++ fi_read_unlock(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++static ssize_t aufs_write(struct file *file, const char __user *__buf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *hidden_file;
++ char __user *buf = (char __user*)__buf;
++ struct inode *h_inode;
++ int dlgt;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(dentry), (unsigned long)count, *ppos);
++
++ inode = dentry->d_inode;
++ i_lock(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
++ /*locked*/1);
++ //if (LktrCond) {fi_write_unlock(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++ err = au_ready_to_write(file, -1);
++ //if (LktrCond) err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* support LSM and notify */
++ dlgt = need_dlgt(sb);
++ hidden_file = au_h_fptr(file);
++ h_inode = hidden_file->f_dentry->d_inode;
++ if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
++ err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
++ else {
++ struct inode *dir = dentry->d_parent->d_inode,
++ *h_dir = hidden_file->f_dentry->d_parent->d_inode;
++ aufs_bindex_t bstart = fbstart(file);
++ hdir_lock(h_dir, dir, bstart);
++ err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
++ hdir_unlock(h_dir, dir, bstart);
++ }
++ ii_write_lock_child(inode);
++ au_cpup_attr_timesizes(inode);
++ ii_write_unlock(inode);
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ i_unlock(inode);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 //def CONFIG_AUFS_ROBR
++struct lvma {
++ struct list_head list;
++ struct vm_area_struct *vma;
++};
++
++static struct file *safe_file(struct vm_area_struct *vma)
++{
++ struct file *file = vma->vm_file;
++ struct super_block *sb = file->f_dentry->d_sb;
++ struct lvma *lvma, *entry;
++ struct aufs_sbinfo *sbinfo;
++ int found, warn;
++
++ TraceEnter();
++ DEBUG_ON(!SB_AUFS(sb));
++
++ warn = 0;
++ found = 0;
++ sbinfo = stosi(sb);
++ spin_lock(&sbinfo->si_lvma_lock);
++ list_for_each_entry(entry, &sbinfo->si_lvma, list) {
++ found = (entry->vma == vma);
++ if (unlikely(found))
++ break;
++ }
++ if (!found) {
++ lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
++ if (lvma) {
++ lvma->vma = vma;
++ list_add(&lvma->list, &sbinfo->si_lvma);
++ } else {
++ warn = 1;
++ file = NULL;
++ }
++ } else
++ file = NULL;
++ spin_unlock(&sbinfo->si_lvma_lock);
++
++ if (unlikely(warn))
++ Warn1("no memory for lvma\n");
++ return file;
++}
++
++static void reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++ struct lvma *entry, *found;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ DEBUG_ON(!SB_AUFS(sb));
++
++ vma->vm_file = file;
++
++ found = NULL;
++ sbinfo = stosi(sb);
++ spin_lock(&sbinfo->si_lvma_lock);
++ list_for_each_entry(entry, &sbinfo->si_lvma, list)
++ if (entry->vma == vma){
++ found = entry;
++ break;
++ }
++ DEBUG_ON(!found);
++ list_del(&found->list);
++ spin_unlock(&sbinfo->si_lvma_lock);
++ kfree(found);
++}
++
++#else
++
++static struct file *safe_file(struct vm_area_struct *vma)
++{
++ struct file *file;
++
++ file = vma->vm_file;
++ if (file->private_data && au_is_aufs(file->f_dentry->d_sb))
++ return file;
++ return NULL;
++}
++
++static void reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ vma->vm_file = file;
++ smp_mb();
++}
++#endif /* CONFIG_AUFS_ROBR */
++
++static struct page *aufs_nopage(struct vm_area_struct *vma, unsigned long addr,
++ int *type)
++{
++ struct page *page;
++ struct dentry *dentry;
++ struct file *file, *hidden_file;
++ struct inode *inode;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct aufs_finfo *finfo;
++
++ TraceEnter();
++ DEBUG_ON(!vma || !vma->vm_file);
++ wait_event(wq, (file = safe_file(vma)));
++ DEBUG_ON(!au_is_aufs(file->f_dentry->d_sb));
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, addr %lx\n", DLNPair(dentry), addr);
++ inode = dentry->d_inode;
++ DEBUG_ON(!S_ISREG(inode->i_mode));
++
++ // do not revalidate, nor lock
++ finfo = ftofi(file);
++ hidden_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ DEBUG_ON(!hidden_file || !au_is_mmapped(file));
++ vma->vm_file = hidden_file;
++ //smp_mb();
++ page = finfo->fi_h_vm_ops->nopage(vma, addr, type);
++ reset_file(vma, file);
++#if 0 //def CONFIG_SMP
++ //wake_up_nr(&wq, online_cpu - 1);
++ wake_up_all(&wq);
++#else
++ wake_up(&wq);
++#endif
++ if (!IS_ERR(page)) {
++ //page->mapping = file->f_mapping;
++ //get_page(page);
++ //file->f_mapping = hidden_file->f_mapping;
++ //touch_atime(NULL, dentry);
++ //inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
++ }
++ TraceErrPtr(page);
++ return page;
++}
++
++static int aufs_populate(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long len, pgprot_t prot, unsigned long pgoff,
++ int nonblock)
++{
++ Err("please report me this application\n");
++ BUG();
++ return ftofi(vma->vm_file)->fi_h_vm_ops->populate
++ (vma, addr, len, prot, pgoff, nonblock);
++}
++
++static struct vm_operations_struct aufs_vm_ops = {
++ //.open = aufs_vmaopen,
++ //.close = aufs_vmaclose,
++ .nopage = aufs_nopage,
++ .populate = aufs_populate,
++ //page_mkwrite(struct vm_area_struct *vma, struct page *page)
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err, wlock, mmapped;
++ struct dentry *dentry;
++ struct super_block *sb;
++ struct file *h_file;
++ struct vm_operations_struct *vm_ops;
++ unsigned long flags;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, %lx, len %lu\n",
++ DLNPair(dentry), vma->vm_start, vma->vm_end - vma->vm_start);
++ DEBUG_ON(!S_ISREG(dentry->d_inode->i_mode));
++ DEBUG_ON(down_write_trylock(&vma->vm_mm->mmap_sem));
++
++ mmapped = au_is_mmapped(file);
++ wlock = 0;
++ if (file->f_mode & FMODE_WRITE) {
++ flags = VM_SHARED | VM_WRITE;
++ wlock = ((flags & vma->vm_flags) == flags);
++ }
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir,
++ wlock | !mmapped, /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ if (wlock) {
++ err = au_ready_to_write(file, -1);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ }
++
++ h_file = au_h_fptr(file);
++ vm_ops = ftofi(file)->fi_h_vm_ops;
++ if (unlikely(!mmapped)) {
++ // nfs uses some locks
++ lockdep_off();
++ err = h_file->f_op->mmap(h_file, vma);
++ lockdep_on();
++ if (unlikely(err))
++ goto out_unlock;
++ vm_ops = vma->vm_ops;
++ DEBUG_ON(!vm_ops);
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (unlikely(err)) {
++ IOErr("failed internal unmapping %.*s, %d\n",
++ DLNPair(h_file->f_dentry), err);
++ err = -EIO;
++ goto out_unlock;
++ }
++ }
++ DEBUG_ON(!vm_ops);
++
++ err = generic_file_mmap(file, vma);
++ if (!err) {
++ file_accessed(h_file);
++ dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
++ vma->vm_ops = &aufs_vm_ops;
++ if (unlikely(!mmapped))
++ ftofi(file)->fi_h_vm_ops = vm_ops;
++ }
++
++ out_unlock:
++ if (!wlock && mmapped)
++ fi_read_unlock(file);
++ else
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++// todo: try do_sendfile() in fs/read_write.c
++static ssize_t aufs_sendfile(struct file *file, loff_t *ppos,
++ size_t count, read_actor_t actor, void *target)
++{
++ ssize_t err;
++ struct file *h_file;
++ const char c = current->comm[4];
++ /* true if a kernel thread named 'loop[0-9].*' accesses a file */
++ const int loopback = (current->mm == NULL
++ && '0' <= c && c <= '9'
++ && strncmp(current->comm, "loop", 4) == 0);
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld, cnt %lu, loopback %d\n",
++ DLNPair(dentry), *ppos, (unsigned long)count, loopback);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ if (unlikely(err))
++ goto out;
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file);
++ if (h_file->f_op && h_file->f_op->sendfile) {
++ if (/* unlikely */(loopback)) {
++ file->f_mapping = h_file->f_mapping;
++ smp_mb(); //??
++ }
++ // nfs uses some locks
++ lockdep_off();
++ err = h_file->f_op->sendfile
++ (h_file, ppos, count, actor, target);
++ lockdep_on();
++ dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
++ }
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* copied from linux/fs/select.h, must match */
++#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
++
++static unsigned int aufs_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask;
++ struct file *hidden_file;
++ int err;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, wait %p\n", DLNPair(dentry), wait);
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode));
++
++ /* We should pretend an error happend. */
++ mask = POLLERR /* | POLLIN | POLLOUT */;
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ /* it is not an error of hidden_file has no operation */
++ mask = DEFAULT_POLLMASK;
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->poll)
++ mask = hidden_file->f_op->poll(hidden_file, wait);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr((int)mask);
++ return mask;
++}
++
++static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err, my_lock;
++ struct inode *inode;
++ struct file *hidden_file;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
++ inode = dentry->d_inode;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++ IMustLock(inode);
++ my_lock = 0;
++#else
++ /* before 2.6.17,
++ * msync(2) calls me without locking i_sem/i_mutex, but fsync(2).
++ */
++ my_lock = !i_trylock(inode);
++#endif
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = 0; //-EBADF; // posix?
++ if (unlikely(!(file->f_mode & FMODE_WRITE)))
++ goto out;
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
++ /*locked*/1);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ err = au_ready_to_write(file, -1);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++
++ err = -EINVAL;
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->fsync) {
++ // todo: apparmor thread?
++ //file->f_mapping->host->i_mutex
++ ii_write_lock_child(inode);
++ hi_lock_child(hidden_file->f_dentry->d_inode);
++ err = hidden_file->f_op->fsync
++ (hidden_file, hidden_file->f_dentry, datasync);
++ //err = -1;
++ au_cpup_attr_timesizes(inode);
++ i_unlock(hidden_file->f_dentry->d_inode);
++ ii_write_unlock(inode);
++ }
++
++ out_unlock:
++ fi_write_unlock(file);
++ out:
++ if (unlikely(my_lock))
++ i_unlock(inode);
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_fasync(int fd, struct file *file, int flag)
++{
++ int err;
++ struct file *hidden_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), flag);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
++ /*locked*/0);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++
++ hidden_file = au_h_fptr(file);
++ if (hidden_file->f_op && hidden_file->f_op->fasync)
++ err = hidden_file->f_op->fasync(fd, hidden_file, flag);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0 // comment
++struct file_operations {
++ struct module *owner;
++ loff_t (*llseek) (struct file *, loff_t, int);
++ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
++ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
++ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
++ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
++ int (*readdir) (struct file *, void *, filldir_t);
++ unsigned int (*poll) (struct file *, struct poll_table_struct *);
++ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
++ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
++ long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
++ int (*mmap) (struct file *, struct vm_area_struct *);
++ int (*open) (struct inode *, struct file *);
++ int (*flush) (struct file *);
++ int (*release) (struct inode *, struct file *);
++ int (*fsync) (struct file *, struct dentry *, int datasync);
++ int (*aio_fsync) (struct kiocb *, int datasync);
++ int (*fasync) (int, struct file *, int);
++ int (*lock) (struct file *, int, struct file_lock *);
++ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
++ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
++ ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
++ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
++ int (*check_flags)(int);
++ int (*dir_notify)(struct file *file, unsigned long arg);
++ int (*flock) (struct file *, int, struct file_lock *);
++};
++#endif
++
++struct file_operations aufs_file_fop = {
++ .read = aufs_read,
++ .write = aufs_write,
++ .poll = aufs_poll,
++ .mmap = aufs_mmap,
++ .open = aufs_open_nondir,
++ .flush = aufs_flush,
++ .release = aufs_release_nondir,
++ .fsync = aufs_fsync_nondir,
++ .fasync = aufs_fasync,
++ .sendfile = aufs_sendfile,
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/file.c linux-2.6.22.1/fs/aufs/file.c
+--- linux-2.6.22.1.oorig/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/file.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,832 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: file.c,v 1.42 2007/05/14 03:39:09 sfjro Exp $ */
++
++//#include <linux/fsnotify.h>
++#include <linux/pagemap.h>
++//#include <linux/poll.h>
++//#include <linux/security.h>
++#include "aufs.h"
++
++/* drop flags for writing */
++unsigned int au_file_roflags(unsigned int flags)
++{
++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
++ flags |= O_RDONLY | O_NOATIME;
++ return flags;
++}
++
++/* common functions to regular file and dir */
++struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
++{
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++ struct super_block *sb;
++ struct vfsmount *hidden_mnt;
++ struct file *hidden_file;
++ struct aufs_branch *br;
++ loff_t old_size;
++ int udba;
++
++ LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
++ DEBUG_ON(!dentry);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ sb = dentry->d_sb;
++ udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++ if (unlikely(udba)) {
++ // test here?
++ }
++
++ br = stobr(sb, bindex);
++ br_get(br);
++ /* drop flags for writing */
++ if (test_ro(sb, bindex, dentry->d_inode))
++ flags = au_file_roflags(flags);
++ flags &= ~O_CREAT;
++ spin_lock(&hidden_inode->i_lock);
++ old_size = i_size_read(hidden_inode);
++ spin_unlock(&hidden_inode->i_lock);
++
++ //DbgSleep(3);
++
++ dget(hidden_dentry);
++ hidden_mnt = mntget(br->br_mnt);
++ hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
++ //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}
++
++ if (!IS_ERR(hidden_file)) {
++#if 0 // remove this
++ if (/* old_size && */ (flags & O_TRUNC)) {
++ au_direval_dec(dentry);
++ if (!IS_ROOT(dentry))
++ au_direval_dec(dentry->d_parent);
++ }
++#endif
++ return hidden_file;
++ }
++
++ br_put(br);
++ TraceErrPtr(hidden_file);
++ return hidden_file;
++}
++
++static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
++{
++ int err;
++ struct dentry *parent, *h_parent, *h_dentry;
++ aufs_bindex_t bcpup;
++ struct inode *h_dir, *h_inode, *dir;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(IS_ROOT(dentry));
++ DiMustWriteLock(dentry);
++
++ parent = dentry->d_parent; // dget_parent()
++ di_write_lock_parent(parent);
++ bcpup = err = find_rw_parent_br(dentry, bstart);
++ //bcpup = err = find_rw_br(sb, bstart);
++ if (unlikely(err < 0)) {
++ err = 0; // stop copyup, it is not an error
++ goto out;
++ }
++ err = 0;
++
++ h_parent = au_h_dptr_i(parent, bcpup);
++ if (!h_parent) {
++ err = cpup_dirs(dentry, bcpup, NULL);
++ if (unlikely(err))
++ goto out;
++ h_parent = au_h_dptr_i(parent, bcpup);
++ }
++
++ h_dir = h_parent->d_inode;
++ h_dentry = au_h_dptr_i(dentry, bstart);
++ h_inode = h_dentry->d_inode;
++ dir = parent->d_inode;
++ hdir_lock(h_dir, dir, bcpup);
++ hi_lock_child(h_inode);
++ DEBUG_ON(au_h_dptr_i(dentry, bcpup));
++ err = sio_cpup_simple(dentry, bcpup, -1,
++ au_flags_cpup(CPUP_DTIME, parent));
++ TraceErr(err);
++ i_unlock(h_inode);
++ hdir_unlock(h_dir, dir, bcpup);
++
++ out:
++ di_write_unlock(parent);
++ TraceErr(err);
++ return err;
++}
++
++int au_do_open(struct inode *inode, struct file *file,
++ int (*open)(struct file *file, int flags))
++{
++ int err, coo;
++ struct dentry *dentry;
++ struct super_block *sb;
++ aufs_bindex_t bstart;
++ struct inode *h_dir, *dir;
++
++ dentry = file->f_dentry;
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++
++ sb = dentry->d_sb;
++ si_read_lock(sb);
++ coo = 0;
++#if 0
++ switch (au_flag_test_coo(sb)) {
++ case AuFlag_COO_LEAF:
++ coo = !S_ISDIR(inode->i_mode);
++ break;
++ case AuFlag_COO_ALL:
++ coo = 1;
++ break;
++ }
++#endif
++ err = au_init_finfo(file);
++ //if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
++ if (unlikely(err))
++ goto out;
++
++ if (!coo) {
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ bstart = dbstart(dentry);
++ } else {
++ di_write_lock_child(dentry);
++ bstart = dbstart(dentry);
++ if (test_ro(sb, bstart, dentry->d_inode)) {
++ err = do_coo(dentry, bstart);
++ if (err) {
++ di_write_unlock(dentry);
++ goto out_finfo;
++ }
++ bstart = dbstart(dentry);
++ }
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ }
++
++ // todo: remove this extra locks
++ dir = dentry->d_parent->d_inode;
++ if (!IS_ROOT(dentry))
++ ii_read_lock_parent(dir);
++ h_dir = au_h_iptr_i(dir, bstart);
++ hdir_lock(h_dir, dir, bstart);
++ err = open(file, file->f_flags);
++ //if (LktrCond) err = -1;
++ hdir_unlock(h_dir, dir, bstart);
++ if (!IS_ROOT(dentry))
++ ii_read_unlock(dir);
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++
++ out_finfo:
++ fi_write_unlock(file);
++ if (unlikely(err))
++ au_fin_finfo(file);
++ //DbgFile(file);
++ out:
++ si_read_unlock(sb);
++ TraceErr(err);
++ return err;
++}
++
++int au_reopen_nondir(struct file *file)
++{
++ int err;
++ struct dentry *dentry;
++ aufs_bindex_t bstart, bindex, bend;
++ struct file *hidden_file, *h_file_tmp;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
++ || !au_h_dptr(dentry)->d_inode);
++ bstart = dbstart(dentry);
++
++ h_file_tmp = NULL;
++ if (fbstart(file) == bstart) {
++ hidden_file = au_h_fptr(file);
++ if (file->f_mode == hidden_file->f_mode)
++ return 0; /* success */
++ h_file_tmp = hidden_file;
++ get_file(h_file_tmp);
++ set_h_fptr(file, bstart, NULL);
++ }
++ DEBUG_ON(fbstart(file) < bstart
++ || ftofi(file)->fi_hfile[0 + bstart].hf_file);
++
++ hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC);
++ //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart));
++ //hidden_file = ERR_PTR(-1);}
++ err = PTR_ERR(hidden_file);
++ if (IS_ERR(hidden_file))
++ goto out; // close all?
++ err = 0;
++ //cpup_file_flags(hidden_file, file);
++ set_fbstart(file, bstart);
++ set_h_fptr(file, bstart, hidden_file);
++ memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //??
++
++ /* close lower files */
++ bend = fbend(file);
++ for (bindex = bstart + 1; bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++ set_fbend(file, bstart);
++
++ out:
++ if (h_file_tmp)
++ fput(h_file_tmp);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * copyup the deleted file for writing.
++ */
++static int cpup_wh_file(struct file *file, aufs_bindex_t bdst, loff_t len)
++{
++ int err;
++ struct dentry *dentry, *parent, *hidden_parent, *tmp_dentry;
++ struct dentry *hidden_dentry_bstart, *hidden_dentry_bdst;
++ struct inode *hidden_dir;
++ aufs_bindex_t bstart;
++ struct aufs_dinfo *dinfo;
++ struct dtime dt;
++ struct lkup_args lkup;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, bdst %d, len %Lu\n", DLNPair(dentry), bdst, len);
++ DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE));
++ DiMustWriteLock(dentry);
++ parent = dentry->d_parent;
++ IiMustAnyLock(parent->d_inode);
++ hidden_parent = au_h_dptr_i(parent, bdst);
++ DEBUG_ON(!hidden_parent);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!hidden_dir);
++ IMustLock(hidden_dir);
++
++ sb = parent->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bdst);
++ lkup.dlgt = need_dlgt(sb);
++ tmp_dentry = lkup_whtmp(hidden_parent, &dentry->d_name, &lkup);
++ //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(tmp_dentry);
++ if (IS_ERR(tmp_dentry))
++ goto out;
++
++ dtime_store(&dt, parent, hidden_parent);
++ dinfo = dtodi(dentry);
++ bstart = dinfo->di_bstart;
++ hidden_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
++ hidden_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
++ dinfo->di_bstart = bdst;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = tmp_dentry;
++ dinfo->di_hdentry[0 + bstart].hd_dentry = au_h_fptr(file)->f_dentry;
++ err = cpup_single(dentry, bdst, bstart, len,
++ au_flags_cpup(!CPUP_DTIME, parent));
++ //if (LktrCond) err = -1;
++ if (!err)
++ err = au_reopen_nondir(file);
++ //err = -1;
++ dinfo->di_hdentry[0 + bstart].hd_dentry = hidden_dentry_bstart;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = hidden_dentry_bdst;
++ dinfo->di_bstart = bstart;
++ if (unlikely(err))
++ goto out_tmp;
++
++ DEBUG_ON(!d_unhashed(dentry));
++ err = vfsub_unlink(hidden_dir, tmp_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1;
++ if (unlikely(err)) {
++ IOErr("failed remove copied-up tmp file %.*s(%d)\n",
++ DLNPair(tmp_dentry), err);
++ err = -EIO;
++ }
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++
++ out_tmp:
++ dput(tmp_dentry);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct cpup_wh_file_args {
++ int *errp;
++ struct file *file;
++ aufs_bindex_t bdst;
++ loff_t len;
++};
++
++static void call_cpup_wh_file(void *args)
++{
++ struct cpup_wh_file_args *a = args;
++ *a->errp = cpup_wh_file(a->file, a->bdst, a->len);
++}
++
++/*
++ * prepare the @file for writing.
++ */
++int au_ready_to_write(struct file *file, loff_t len)
++{
++ int err;
++ struct dentry *dentry, *parent, *hidden_dentry, *hidden_parent;
++ struct inode *hidden_inode, *hidden_dir, *inode, *dir;
++ struct super_block *sb;
++ aufs_bindex_t bstart, bcpup;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, len %Ld\n", DLNPair(dentry), len);
++ FiMustWriteLock(file);
++
++ sb = dentry->d_sb;
++ bstart = fbstart(file);
++ DEBUG_ON(ftobr(file, bstart) != stobr(sb, bstart));
++
++ inode = dentry->d_inode;
++ ii_read_lock_child(inode);
++ LKTRTrace("rdonly %d, bstart %d\n", test_ro(sb, bstart, inode), bstart);
++ err = test_ro(sb, bstart, inode);
++ ii_read_unlock(inode);
++ if (!err && (au_h_fptr(file)->f_mode & FMODE_WRITE))
++ return 0;
++
++ /* need to cpup */
++ parent = dentry->d_parent; // dget_parent()
++ di_write_lock_child(dentry);
++ di_write_lock_parent(parent);
++ bcpup = err = find_rw_parent_br(dentry, bstart);
++ //bcpup = err = find_rw_br(sb, bstart);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ err = 0;
++
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ if (!hidden_parent) {
++ err = cpup_dirs(dentry, bcpup, NULL);
++ //if (LktrCond) err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ }
++
++ hidden_dir = hidden_parent->d_inode;
++ hidden_dentry = au_h_fptr(file)->f_dentry;
++ hidden_inode = hidden_dentry->d_inode;
++ dir = parent->d_inode;
++ hdir_lock(hidden_dir, dir, bcpup);
++ hi_lock_child(hidden_inode);
++ if (d_unhashed(dentry) || d_unhashed(hidden_dentry)
++ /* || !hidden_inode->i_nlink */) {
++ if (!au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE,
++ need_dlgt(sb)))
++ err = cpup_wh_file(file, bcpup, len);
++ else {
++ struct cpup_wh_file_args args = {
++ .errp = &err,
++ .file = file,
++ .bdst = bcpup,
++ .len = len
++ };
++ au_wkq_wait(call_cpup_wh_file, &args, /*dlgt*/0);
++ }
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ } else {
++ if (!au_h_dptr_i(dentry, bcpup))
++ err = sio_cpup_simple(dentry, bcpup, len,
++ au_flags_cpup(CPUP_DTIME,
++ parent));
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ if (!err)
++ err = au_reopen_nondir(file);
++ //if (LktrCond) err = -1;
++ TraceErr(err);
++ }
++ i_unlock(hidden_inode);
++ hdir_unlock(hidden_dir, dir, bcpup);
++
++ out_unlock:
++ di_write_unlock(parent);
++ di_write_unlock(dentry);
++// out:
++ TraceErr(err);
++ return err;
++
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * after branch manipulating, refresh the file.
++ */
++static int refresh_file(struct file *file, int (*reopen)(struct file *file))
++{
++ int err, new_sz;
++ struct dentry *dentry;
++ aufs_bindex_t bend, bindex, bstart, brid;
++ struct aufs_hfile *p;
++ struct aufs_finfo *finfo;
++ struct super_block *sb;
++ struct inode *inode;
++ struct file *hidden_file;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ FiMustWriteLock(file);
++ DiMustReadLock(dentry);
++ inode = dentry->d_inode;
++ IiMustReadLock(inode);
++ //au_debug_on();
++ //DbgDentry(dentry);
++ //DbgFile(file);
++ //au_debug_off();
++
++ err = -ENOMEM;
++ sb = dentry->d_sb;
++ finfo = ftofi(file);
++ bstart = finfo->fi_bstart;
++ bend = finfo->fi_bstart;
++ new_sz = sizeof(*finfo->fi_hfile) * (sbend(sb) + 1);
++ p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++ finfo->fi_hfile = p;
++ hidden_file = p[0 + bstart].hf_file;
++
++ p = finfo->fi_hfile + finfo->fi_bstart;
++ brid = p->hf_br->br_id;
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
++ struct aufs_hfile tmp, *q;
++ aufs_bindex_t new_bindex;
++
++ if (!p->hf_file)
++ continue;
++ new_bindex = find_bindex(sb, p->hf_br);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) { // test here
++ set_h_fptr(file, bindex, NULL);
++ continue;
++ }
++
++ /* swap two hidden inode, and loop again */
++ q = finfo->fi_hfile + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hf_file) {
++ bindex--;
++ p--;
++ }
++ }
++ {
++ aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
++ finfo->fi_bstart = 0;
++ finfo->fi_bend = sbend(sb);
++ //au_debug_on();
++ //DbgFile(file);
++ //au_debug_off();
++ finfo->fi_bstart = s;
++ finfo->fi_bend = e;
++ }
++
++ p = finfo->fi_hfile;
++ if (!au_is_mmapped(file) && !d_unhashed(dentry)) {
++ bend = sbend(sb);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p);
++ }
++ } else {
++ bend = find_brindex(sb, brid);
++ //LKTRTrace("%d\n", bend);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file)
++ au_hfput(p);
++ //LKTRTrace("%d\n", finfo->fi_bstart);
++ bend = sbend(sb);
++ }
++
++ p = finfo->fi_hfile + bend;
++ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
++ finfo->fi_bend--, p--)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p);
++ }
++ //Dbg("%d, %d\n", finfo->fi_bstart, finfo->fi_bend);
++ DEBUG_ON(finfo->fi_bend < finfo->fi_bstart);
++ //DbgFile(file);
++ //DbgDentry(file->f_dentry);
++
++ err = 0;
++#if 0 // todo:
++ if (!au_h_dptr(dentry)->d_inode) {
++ au_update_figen(file);
++ goto out; /* success */
++ }
++#endif
++
++ if (unlikely(au_is_mmapped(file) || d_unhashed(dentry)))
++ goto out_update; /* success */
++
++ again:
++ bstart = ibstart(inode);
++ if (bstart < finfo->fi_bstart
++ && au_flag_test(sb, AuFlag_PLINK)
++ && au_is_plinked(sb, inode)) {
++ struct dentry *parent = dentry->d_parent; // dget_parent()
++ struct inode *dir = parent->d_inode, *h_dir;
++
++ if (test_ro(sb, bstart, inode)) {
++ di_read_lock_parent(parent, !AUFS_I_RLOCK);
++ bstart = err = find_rw_parent_br(dentry, bstart);
++ //bstart = err = find_rw_br(sb, bstart);
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ //todo: err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ di_write_lock_child(dentry);
++ if (bstart != ibstart(inode)) { // todo
++ /* someone changed our inode while we were sleeping */
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ goto again;
++ }
++
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ err = test_and_cpup_dirs(dentry, bstart, NULL);
++
++ // always superio.
++#if 1
++ h_dir = au_h_dptr_i(parent, bstart)->d_inode;
++ hdir_lock(h_dir, dir, bstart);
++ err = sio_cpup_simple(dentry, bstart, -1,
++ au_flags_cpup(CPUP_DTIME, parent));
++ hdir_unlock(h_dir, dir, bstart);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++#else
++ if (!is_au_wkq(current)) {
++ struct cpup_pseudo_link_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bstart,
++ .do_lock = 1
++ };
++ au_wkq_wait(call_cpup_pseudo_link, &args);
++ } else
++ err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
++#endif
++ di_downgrade_lock(dentry, AUFS_I_RLOCK);
++ if (unlikely(err))
++ goto out;
++ }
++
++ err = reopen(file);
++ //err = -1;
++ out_update:
++ if (!err) {
++ au_update_figen(file);
++ //DbgFile(file);
++ return 0; /* success */
++ }
++
++ /* error, close all hidden files */
++ bend = fbend(file);
++ for (bindex = fbstart(file); bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* common function to regular file and dir */
++int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
++ int wlock, int locked)
++{
++ int err, sgen, fgen, pseudo_link;
++ struct dentry *dentry;
++ struct super_block *sb;
++ aufs_bindex_t bstart;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, w %d, l %d\n", DLNPair(dentry), wlock, locked);
++ sb = dentry->d_sb;
++ SiMustAnyLock(sb);
++
++ err = 0;
++ sgen = au_sigen(sb);
++ fi_write_lock(file);
++ fgen = au_figen(file);
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ bstart = dbstart(dentry);
++ pseudo_link = (bstart != ibstart(dentry->d_inode));
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ if (sgen == fgen && !pseudo_link && fbstart(file) == bstart) {
++ if (!wlock)
++ fi_downgrade_lock(file);
++ return 0; /* success */
++ }
++
++ LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
++ if (sgen != au_digen(dentry)) {
++ /*
++ * d_path() and path_lookup() is a simple and good approach
++ * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
++ * deadlock. removed the code.
++ */
++ di_write_lock_child(dentry);
++ err = au_reval_dpath(dentry, sgen);
++ //if (LktrCond) err = -1;
++ di_write_unlock(dentry);
++ if (unlikely(err < 0))
++ goto out;
++ DEBUG_ON(au_digen(dentry) != sgen);
++ }
++
++ di_read_lock_child(dentry, AUFS_I_RLOCK);
++ err = refresh_file(file, reopen);
++ //if (LktrCond) err = -1;
++ di_read_unlock(dentry, AUFS_I_RLOCK);
++ if (!err) {
++ if (!wlock)
++ fi_downgrade_lock(file);
++ } else
++ fi_write_unlock(file);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++// cf. aufs_nopage()
++// for madvise(2)
++static int aufs_readpage(struct file *file, struct page *page)
++{
++ TraceEnter();
++ unlock_page(page);
++ return 0;
++}
++
++// they will never be called.
++#ifdef CONFIG_AUFS_DEBUG
++static int aufs_prepare_write(struct file *file, struct page *page,
++ unsigned from, unsigned to)
++{BUG();return 0;}
++static int aufs_commit_write(struct file *file, struct page *page,
++ unsigned from, unsigned to)
++{BUG();return 0;}
++static int aufs_writepage(struct page *page, struct writeback_control *wbc)
++{BUG();return 0;}
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++static void aufs_sync_page(struct page *page)
++{BUG();}
++#else
++static int aufs_sync_page(struct page *page)
++{BUG(); return 0;}
++#endif
++
++#if 0 // comment
++static int aufs_writepages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{BUG();return 0;}
++static int aufs_readpages(struct file *filp, struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages)
++{BUG();return 0;}
++static sector_t aufs_bmap(struct address_space *mapping, sector_t block)
++{BUG();return 0;}
++#endif
++
++static int aufs_set_page_dirty(struct page *page)
++{BUG();return 0;}
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++static void aufs_invalidatepage (struct page *page, unsigned long offset)
++{BUG();}
++#else
++static int aufs_invalidatepage (struct page *page, unsigned long offset)
++{BUG(); return 0;}
++#endif
++static int aufs_releasepage (struct page *page, gfp_t gfp)
++{BUG();return 0;}
++static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs)
++{BUG();return 0;}
++static struct page* aufs_get_xip_page(struct address_space *mapping,
++ sector_t offset, int create)
++{BUG();return NULL;}
++//static int aufs_migratepage (struct page *newpage, struct page *page)
++//{BUG();return 0;}
++#endif
++
++#if 0 // comment
++struct address_space {
++ struct inode *host; /* owner: inode, block_device */
++ struct radix_tree_root page_tree; /* radix tree of all pages */
++ rwlock_t tree_lock; /* and rwlock protecting it */
++ unsigned int i_mmap_writable;/* count VM_SHARED mappings */
++ struct prio_tree_root i_mmap; /* tree of private and shared mappings */
++ struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
++ spinlock_t i_mmap_lock; /* protect tree, count, list */
++ unsigned int truncate_count; /* Cover race condition with truncate */
++ unsigned long nrpages; /* number of total pages */
++ pgoff_t writeback_index;/* writeback starts here */
++ struct address_space_operations *a_ops; /* methods */
++ unsigned long flags; /* error bits/gfp mask */
++ struct backing_dev_info *backing_dev_info; /* device readahead, etc */
++ spinlock_t private_lock; /* for use by the address_space */
++ struct list_head private_list; /* ditto */
++ struct address_space *assoc_mapping; /* ditto */
++} __attribute__((aligned(sizeof(long))));
++
++struct address_space_operations {
++ int (*writepage)(struct page *page, struct writeback_control *wbc);
++ int (*readpage)(struct file *, struct page *);
++ void (*sync_page)(struct page *);
++
++ /* Write back some dirty pages from this mapping. */
++ int (*writepages)(struct address_space *, struct writeback_control *);
++
++ /* Set a page dirty. Return true if this dirtied it */
++ int (*set_page_dirty)(struct page *page);
++
++ int (*readpages)(struct file *filp, struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages);
++
++ /*
++ * ext3 requires that a successful prepare_write() call be followed
++ * by a commit_write() call - they must be balanced
++ */
++ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
++ int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
++ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
++ sector_t (*bmap)(struct address_space *, sector_t);
++ void (*invalidatepage) (struct page *, unsigned long);
++ int (*releasepage) (struct page *, gfp_t);
++ ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
++ loff_t offset, unsigned long nr_segs);
++ struct page* (*get_xip_page)(struct address_space *, sector_t,
++ int);
++ /* migrate the contents of a page to the specified target */
++ int (*migratepage) (struct page *, struct page *);
++};
++#endif
++
++struct address_space_operations aufs_aop = {
++ .readpage = aufs_readpage,
++#ifdef CONFIG_AUFS_DEBUG
++ .writepage = aufs_writepage,
++ .sync_page = aufs_sync_page,
++ //.writepages = aufs_writepages,
++ .set_page_dirty = aufs_set_page_dirty,
++ //.readpages = aufs_readpages,
++ .prepare_write = aufs_prepare_write,
++ .commit_write = aufs_commit_write,
++ //.bmap = aufs_bmap,
++ .invalidatepage = aufs_invalidatepage,
++ .releasepage = aufs_releasepage,
++ .direct_IO = aufs_direct_IO,
++ .get_xip_page = aufs_get_xip_page,
++ //.migratepage = aufs_migratepage
++#endif
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/file.h linux-2.6.22.1/fs/aufs/file.h
+--- linux-2.6.22.1.oorig/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/file.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: file.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_FILE_H__
++#define __AUFS_FILE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++// SEEK_xxx are defined in linux/fs.h
++#else
++enum {SEEK_SET, SEEK_CUR, SEEK_END};
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_branch;
++struct aufs_hfile {
++ struct file *hf_file;
++ struct aufs_branch *hf_br;
++};
++
++struct aufs_vdir;
++struct aufs_finfo {
++ atomic_t fi_generation;
++
++ struct aufs_rwsem fi_rwsem;
++ struct aufs_hfile *fi_hfile;
++ aufs_bindex_t fi_bstart, fi_bend;
++
++ union {
++ struct vm_operations_struct *fi_h_vm_ops;
++ struct aufs_vdir *fi_vdir_cache;
++ };
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* file.c */
++extern struct address_space_operations aufs_aop;
++unsigned int au_file_roflags(unsigned int flags);
++struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex,
++ int flags);
++int au_do_open(struct inode *inode, struct file *file,
++ int (*open)(struct file *file, int flags));
++int au_reopen_nondir(struct file *file);
++int au_ready_to_write(struct file *file, loff_t len);
++int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
++ int wlock, int locked);
++
++/* f_op.c */
++extern struct file_operations aufs_file_fop;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++int aufs_flush(struct file *file, fl_owner_t id);
++#else
++int aufs_flush(struct file *file);
++#endif
++
++/* finfo.c */
++struct aufs_finfo *ftofi(struct file *file);
++aufs_bindex_t fbstart(struct file *file);
++aufs_bindex_t fbend(struct file *file);
++struct aufs_vdir *fvdir_cache(struct file *file);
++struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex);
++struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex);
++struct file *au_h_fptr(struct file *file);
++
++void set_fbstart(struct file *file, aufs_bindex_t bindex);
++void set_fbend(struct file *file, aufs_bindex_t bindex);
++void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache);
++void au_hfput(struct aufs_hfile *hf);
++void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *h_file);
++void au_update_figen(struct file *file);
++
++void au_fin_finfo(struct file *file);
++int au_init_finfo(struct file *file);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_figen(struct file *f)
++{
++ return atomic_read(&ftofi(f)->fi_generation);
++}
++
++static inline int au_is_mmapped(struct file *f)
++{
++ return !!(ftofi(f)->fi_h_vm_ops);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * fi_read_lock, fi_write_lock,
++ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
++ */
++SimpleRwsemFuncs(fi, struct file *f, ftofi(f)->fi_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define FiMustReadLock(f) do {\
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustReadLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustWriteLock(f) do { \
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustWriteLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustAnyLock(f) do { \
++ SiMustAnyLock((f)->f_dentry->d_sb); \
++ RwMustAnyLock(&ftofi(f)->fi_rwsem); \
++} while (0)
++
++#define FiMustNoWaiters(f) RwMustNoWaiters(&ftofi(f)->fi_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FILE_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/finfo.c linux-2.6.22.1/fs/aufs/finfo.c
+--- linux-2.6.22.1.oorig/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/finfo.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,211 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: finfo.c,v 1.23 2007/04/30 05:45:21 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct aufs_finfo *ftofi(struct file *file)
++{
++ struct aufs_finfo *finfo = file->private_data;
++ DEBUG_ON(!finfo
++ || !finfo->fi_hfile
++ || (0 < finfo->fi_bend
++ && (/* stosi(file->f_dentry->d_sb)->si_bend
++ < finfo->fi_bend
++ || */ finfo->fi_bend < finfo->fi_bstart)));
++ return finfo;
++}
++
++// hard/soft set
++aufs_bindex_t fbstart(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_bstart;
++}
++
++aufs_bindex_t fbend(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_bend;
++}
++
++struct aufs_vdir *fvdir_cache(struct file *file)
++{
++ FiMustAnyLock(file);
++ return ftofi(file)->fi_vdir_cache;
++}
++
++struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustAnyLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_br && br_count(hf->hf_br) <= 0);
++ return hf->hf_br;
++}
++
++struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustAnyLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_file
++ && file_count(hf->hf_file) <= 0
++ && br_count(hf->hf_br) <= 0);
++ return hf->hf_file;
++}
++
++struct file *au_h_fptr(struct file *file)
++{
++ return au_h_fptr_i(file, fbstart(file));
++}
++
++void set_fbstart(struct file *file, aufs_bindex_t bindex)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex);
++ ftofi(file)->fi_bstart = bindex;
++}
++
++void set_fbend(struct file *file, aufs_bindex_t bindex)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex
++ || bindex < fbstart(file));
++ ftofi(file)->fi_bend = bindex;
++}
++
++void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache)
++{
++ FiMustWriteLock(file);
++ DEBUG_ON(!S_ISDIR(file->f_dentry->d_inode->i_mode)
++ || (ftofi(file)->fi_vdir_cache && vdir_cache));
++ ftofi(file)->fi_vdir_cache = vdir_cache;
++}
++
++void au_hfput(struct aufs_hfile *hf)
++{
++ fput(hf->hf_file);
++ hf->hf_file = NULL;
++ DEBUG_ON(!hf->hf_br);
++ br_put(hf->hf_br);
++ hf->hf_br = NULL;
++}
++
++void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
++{
++ struct aufs_finfo *finfo = ftofi(file);
++ struct aufs_hfile *hf;
++
++ FiMustWriteLock(file);
++ DEBUG_ON(!finfo
++ || finfo->fi_bstart < 0
++ || bindex < finfo->fi_bstart
++ || finfo->fi_bend < bindex);
++ DEBUG_ON(val && file_count(val) <= 0);
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(val && hf->hf_file);
++ if (hf->hf_file)
++ au_hfput(hf);
++ if (val) {
++ hf->hf_file = val;
++ hf->hf_br = stobr(file->f_dentry->d_sb, bindex);
++ }
++}
++
++void au_update_figen(struct file *file)
++{
++ atomic_set(&ftofi(file)->fi_generation, au_digen(file->f_dentry));
++}
++
++void au_fin_finfo(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ struct dentry *dentry;
++ aufs_bindex_t bindex, bend;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ SiMustAnyLock(dentry->d_sb);
++
++ fi_write_lock(file);
++ bend = fbend(file);
++ bindex = fbstart(file);
++ if (bindex >= 0)
++ for (; bindex <= bend; bindex++)
++ set_h_fptr(file, bindex, NULL);
++
++ finfo = ftofi(file);
++#ifdef CONFIG_AUFS_DEBUG
++ if (finfo->fi_bstart >= 0) {
++ bend = fbend(file);
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
++ struct aufs_hfile *hf;
++ hf = finfo->fi_hfile + bindex;
++ DEBUG_ON(hf->hf_file || hf->hf_br);
++ }
++ }
++#endif
++
++ kfree(finfo->fi_hfile);
++ fi_write_unlock(file);
++ cache_free_finfo(finfo);
++ //file->private_data = NULL;
++}
++
++int au_init_finfo(struct file *file)
++{
++ struct aufs_finfo *finfo;
++ struct dentry *dentry;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ DEBUG_ON(!dentry->d_inode);
++
++ finfo = cache_alloc_finfo();
++ if (finfo) {
++ finfo->fi_hfile = kcalloc(sbend(dentry->d_sb) + 1,
++ sizeof(*finfo->fi_hfile), GFP_KERNEL);
++ if (finfo->fi_hfile) {
++ rw_init_wlock(&finfo->fi_rwsem);
++ finfo->fi_bstart = -1;
++ finfo->fi_bend = -1;
++ atomic_set(&finfo->fi_generation, au_digen(dentry));
++
++ file->private_data = finfo;
++ return 0; /* success */
++ }
++ cache_free_finfo(finfo);
++ }
++
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/hinotify.c linux-2.6.22.1/fs/aufs/hinotify.c
+--- linux-2.6.22.1.oorig/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/hinotify.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,536 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: hinotify.c,v 1.19 2007/05/14 03:39:21 sfjro Exp $ */
++
++#include "aufs.h"
++
++static struct inotify_handle *in_handle;
++static const __u32 in_mask = (IN_MOVE | IN_DELETE | IN_CREATE /* | IN_ACCESS */
++ | IN_MODIFY | IN_ATTRIB
++ | IN_DELETE_SELF | IN_MOVE_SELF);
++
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *hidden_inode)
++{
++ int err;
++ struct aufs_hinotify *hin;
++ s32 wd;
++
++ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, hidden_inode->i_ino);
++
++ err = -ENOMEM;
++ hin = cache_alloc_hinotify();
++ if (hin) {
++ DEBUG_ON(hinode->hi_notify);
++ hinode->hi_notify = hin;
++ hin->hin_aufs_inode = inode;
++ inotify_init_watch(&hin->hin_watch);
++ wd = inotify_add_watch(in_handle, &hin->hin_watch, hidden_inode,
++ in_mask);
++ if (wd >= 0)
++ return 0; /* success */
++
++ err = wd;
++ put_inotify_watch(&hin->hin_watch);
++ cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++void do_free_hinotify(struct aufs_hinode *hinode)
++{
++ int err;
++ struct aufs_hinotify *hin;
++
++ TraceEnter();
++
++ hin = hinode->hi_notify;
++ if (hin) {
++ err = 0;
++ if (atomic_read(&hin->hin_watch.count))
++ err = inotify_rm_watch(in_handle, &hin->hin_watch);
++
++ if (!err) {
++ cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ } else
++ IOErr1("failed inotify_rm_watch() %d\n", err);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void ctl_hinotify(struct aufs_hinode *hinode, const __u32 mask)
++{
++ struct inode *hi;
++ struct inotify_watch *watch;
++
++ hi = hinode->hi_inode;
++ LKTRTrace("hi%lu, sb %p, 0x%x\n", hi->i_ino, hi->i_sb, mask);
++ if (0 && !strcmp(current->comm, "link"))
++ dump_stack();
++ IMustLock(hi);
++ if (!hinode->hi_notify)
++ return;
++
++ watch = &hinode->hi_notify->hin_watch;
++#if 0
++ {
++ u32 wd;
++ wd = inotify_find_update_watch(in_handle, hi, mask);
++ TraceErr(wd);
++ // ignore an err;
++ }
++#else
++ watch->mask = mask;
++ smp_mb();
++#endif
++ LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
++}
++
++#define suspend_hinotify(hi) ctl_hinotify(hi, 0)
++#define resume_hinotify(hi) ctl_hinotify(hi, in_mask)
++
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("i%lu, b%d, lsc %d\n", dir->i_ino, bindex, lsc);
++ DEBUG_ON(!S_ISDIR(dir->i_mode));
++ hinode = itoii(dir)->ii_hinode + bindex;
++ DEBUG_ON(h_dir != hinode->hi_inode);
++
++ hi_lock(h_dir, lsc);
++ if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
++ suspend_hinotify(hinode);
++}
++
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("i%lu, b%d\n", dir->i_ino, bindex);
++ DEBUG_ON(!S_ISDIR(dir->i_mode));
++ hinode = itoii(dir)->ii_hinode + bindex;
++ DEBUG_ON(h_dir != hinode->hi_inode);
++
++ if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
++ resume_hinotify(hinode);
++ i_unlock(h_dir);
++}
++
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
++
++ vfsub_lock_rename(h_parents[0], h_parents[1]);
++ hinode = itoii(dirs[0])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
++ suspend_hinotify(hinode);
++ if (issamedir)
++ return;
++ hinode = itoii(dirs[1])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
++ suspend_hinotify(hinode);
++}
++
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ struct aufs_hinode *hinode;
++
++ LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
++
++ hinode = itoii(dirs[0])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
++ resume_hinotify(hinode);
++ if (!issamedir) {
++ hinode = itoii(dirs[1])->ii_hinode + bindex;
++ DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
++ resume_hinotify(hinode);
++ }
++ vfsub_unlock_rename(h_parents[0], h_parents[1]);
++}
++
++void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ aufs_bindex_t bindex, bend;
++ struct inode *hi;
++
++ LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
++
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); bindex <= bend; bindex++) {
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi) {
++ //hi_lock(hi, AUFS_LSC_H_CHILD);
++ igrab(hi);
++ set_h_iptr(inode, bindex, NULL, 0);
++ set_h_iptr(inode, bindex, igrab(hi), flags);
++ iput(hi);
++ //i_unlock(hi);
++ }
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DEBUG
++static char *in_name(u32 mask)
++{
++#define test_ret(flag) if (mask & flag) return #flag;
++ test_ret(IN_ACCESS);
++ test_ret(IN_MODIFY);
++ test_ret(IN_ATTRIB);
++ test_ret(IN_CLOSE_WRITE);
++ test_ret(IN_CLOSE_NOWRITE);
++ test_ret(IN_OPEN);
++ test_ret(IN_MOVED_FROM);
++ test_ret(IN_MOVED_TO);
++ test_ret(IN_CREATE);
++ test_ret(IN_DELETE);
++ test_ret(IN_DELETE_SELF);
++ test_ret(IN_MOVE_SELF);
++ test_ret(IN_UNMOUNT);
++ test_ret(IN_Q_OVERFLOW);
++ test_ret(IN_IGNORED);
++ return "";
++#undef test_ret
++}
++#else
++#define in_name(m) "??"
++#endif
++
++static int dec_gen_by_name(struct inode *dir, const char *_name, u32 mask)
++{
++ int err;
++ struct dentry *parent, *child;
++ struct inode *inode;
++ struct qstr *dname;
++ char *name = (void*)_name;
++ unsigned int len;
++
++ LKTRTrace("i%lu, %s, 0x%x %s\n",
++ dir->i_ino, name, mask, in_name(mask));
++
++ err = -1;
++ parent = d_find_alias(dir);
++ if (unlikely(!parent))
++ goto out;
++
++#if 0
++ if (unlikely(!memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ name += AUFS_WH_PFX_LEN;
++#endif
++ len = strlen(name);
++ spin_lock(&dcache_lock);
++ list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
++ dname = &child->d_name;
++ if (len == dname->len && !memcmp(dname->name, name, len)) {
++ au_digen_dec(child);
++#if 1
++ //todo: why both are needed
++ if (mask & IN_MOVE) {
++ spin_lock(&child->d_lock);
++ __d_drop(child);
++ spin_unlock(&child->d_lock);
++ }
++#endif
++
++ inode = child->d_inode;
++ if (inode)
++ au_iigen_dec(inode);
++ err = !!inode;
++
++ // todo: the i_nlink of newly created name by link(2)
++ // should be updated
++ // todo: some nfs dentry doesn't notified at deleteing
++ break;
++ }
++ }
++ spin_unlock(&dcache_lock);
++ dput(parent);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct postproc_args {
++ struct inode *h_dir, *dir, *h_child_inode;
++ char *h_child_name;
++ u32 mask;
++};
++
++static void dec_gen_by_ino(struct postproc_args *a)
++{
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend, bfound;
++ struct xino xino;
++ struct inode *cinode;
++
++ TraceEnter();
++
++ sb = a->dir->i_sb;
++ DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++
++ bfound = -1;
++ bend = ibend(a->dir);
++ for (bindex = ibstart(a->dir); bfound == -1 && bindex <= bend; bindex++)
++ if (au_h_iptr_i(a->dir, bindex) == a->h_dir)
++ bfound = bindex;
++ if (bfound < 0)
++ return;
++
++ bindex = find_brindex(sb, itoii(a->dir)->ii_hinode[bfound + 0].hi_id);
++ if (bindex < 0)
++ return;
++ if (unlikely(xino_read(sb, bindex, a->h_child_inode->i_ino, &xino)))
++ return;
++ cinode = NULL;
++ if (xino.ino)
++ cinode = ilookup(sb, xino.ino);
++ if (cinode) {
++#if 1
++ if (1 || a->mask & IN_MOVE) {
++ struct dentry *child;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(child, &cinode->i_dentry, d_alias)
++ au_digen_dec(child);
++ spin_unlock(&dcache_lock);
++ }
++#endif
++ au_iigen_dec(cinode);
++ iput(cinode);
++ }
++}
++
++static void reset_ino(struct postproc_args *a)
++{
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++ struct inode *h_dir;
++
++ sb = a->dir->i_sb;
++ bend = ibend(a->dir);
++ for (bindex = ibstart(a->dir); bindex <= bend; bindex++) {
++ h_dir = au_h_iptr_i(a->dir, bindex);
++ if (h_dir && h_dir != a->h_dir)
++ xino_write0(sb, bindex, h_dir->i_ino);
++ /* ignore this error */
++ }
++}
++
++static void postproc(void *args)
++{
++ struct postproc_args *a = args;
++ struct super_block *sb;
++ struct aufs_vdir *vdir;
++
++ //au_debug_on();
++ LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++ DEBUG_ON(!a->dir);
++#if 0//def ForceInotify
++ Dbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++#endif
++
++ i_lock(a->dir);
++ sb = a->dir->i_sb;
++ si_read_lock(sb); // consider write_lock
++ ii_write_lock_parent(a->dir);
++
++ /* make dir entries obsolete */
++ vdir = ivdir(a->dir);
++ if (vdir)
++ vdir->vd_jiffy = 0;
++ a->dir->i_version++;
++
++ /*
++ * special handling root directory,
++ * sine d_revalidate may not be called later.
++ * main purpose is maintaining i_nlink.
++ */
++ if (unlikely(a->dir->i_ino == AUFS_ROOT_INO))
++ au_cpup_attr_all(a->dir);
++
++ if (a->h_child_inode && au_flag_test(sb, AuFlag_XINO))
++ dec_gen_by_ino(a);
++ else if (a->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
++ reset_ino(a);
++
++ ii_write_unlock(a->dir);
++ si_read_unlock(sb);
++ i_unlock(a->dir);
++
++ au_mntput(a->dir->i_sb);
++ iput(a->h_child_inode);
++ iput(a->h_dir);
++ iput(a->dir);
++#if 0
++ if (atomic_dec_and_test(&stosi(sb)->si_hinotify))
++ wake_up_all(&stosi(sb)->si_hinotify_wq);
++#endif
++ kfree(a);
++ //au_debug_off();
++}
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
++ u32 cookie, const char *h_child_name,
++ struct inode *h_child_inode)
++{
++ struct aufs_hinotify *hinotify;
++ struct postproc_args *args;
++ int len;
++ char *p;
++ struct inode *dir;
++ //static DECLARE_WAIT_QUEUE_HEAD(wq);
++
++ //au_debug_on();
++ LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++ //au_debug_off();
++ //IMustLock(h_dir);
++#if 0 //defined(ForceInotify) || defined(DbgInotify)
++ Dbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++#endif
++ /* if IN_UNMOUNT happens, there must be another bug */
++ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++ put_inotify_watch(watch);
++ return;
++ }
++
++ switch (mask & IN_ALL_EVENTS) {
++ case IN_MODIFY:
++ case IN_ATTRIB:
++ if (h_child_name)
++ return;
++ break;
++
++ case IN_MOVED_FROM:
++ case IN_MOVED_TO:
++ case IN_CREATE:
++ DEBUG_ON(!h_child_name || !h_child_inode);
++ break;
++ case IN_DELETE:
++ /*
++ * aufs never be able to get this child inode.
++ * revalidation should be in d_revalide()
++ * by checking i_nlink, i_generation or d_unhashed().
++ */
++ DEBUG_ON(!h_child_name);
++ break;
++
++ case IN_DELETE_SELF:
++ case IN_MOVE_SELF:
++ DEBUG_ON(h_child_name || h_child_inode);
++ break;
++
++ case IN_ACCESS:
++ default:
++ DEBUG_ON(1);
++ }
++
++#ifdef DbgInotify
++ WARN_ON(1);
++#endif
++
++ /* iput() will be called in postproc() */
++ hinotify = container_of(watch, struct aufs_hinotify, hin_watch);
++ DEBUG_ON(!hinotify || !hinotify->hin_aufs_inode);
++ dir = hinotify->hin_aufs_inode;
++
++ /* force re-lookup in next d_revalidate() */
++ if (dir->i_ino != AUFS_ROOT_INO)
++ au_iigen_dec(dir);
++ len = 0;
++ if (h_child_name && dec_gen_by_name(dir, h_child_name, mask))
++ len = strlen(h_child_name);
++
++ //wait_event(wq, (args = kmalloc(sizeof(*args), GFP_KERNEL)));
++ args = kmalloc(sizeof(*args) + len + 1, GFP_KERNEL);
++ if (unlikely(!args)) {
++ Err("no memory\n");
++ return;
++ }
++ args->mask = mask;
++ args->dir = igrab(dir);
++ args->h_dir = igrab(watch->inode);
++ args->h_child_inode = NULL;
++ if (len) {
++ if (h_child_inode)
++ args->h_child_inode = igrab(h_child_inode);
++ p = (void*)args;
++ args->h_child_name = p + sizeof(*args);
++ memcpy(args->h_child_name, h_child_name, len + 1);
++ }
++ //atomic_inc(&stosi(args->dir->i_sb)->si_hinotify);
++ /* prohibit umount */
++ au_mntget(args->dir->i_sb);
++ au_wkq_nowait(postproc, args, /*dlgt*/0);
++}
++
++#if 0
++void hinotify_flush(struct super_block *sb)
++{
++ atomic_t *p = &stosi(sb)->si_hinotify;
++ wait_event(stosi(sb)->si_hinotify_wq, !atomic_read(p));
++}
++#endif
++
++static void aufs_inotify_destroy(struct inotify_watch *watch)
++{
++ return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++ .handle_event = aufs_inotify,
++ .destroy_watch = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++int __init au_inotify_init(void)
++{
++ in_handle = inotify_init(&aufs_inotify_ops);
++ if (!IS_ERR(in_handle))
++ return 0;
++ TraceErrPtr(in_handle);
++ return PTR_ERR(in_handle);
++}
++
++void au_inotify_fin(void)
++{
++ inotify_destroy(in_handle);
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op.c linux-2.6.22.1/fs/aufs/i_op.c
+--- linux-2.6.22.1.oorig/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/i_op.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,641 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op.c,v 1.30 2007/04/23 00:55:05 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include <linux/security.h>
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++#ifdef CONFIG_AUFS_DLGT
++struct security_inode_permission_args {
++ int *errp;
++ struct inode *h_inode;
++ int mask;
++ struct nameidata *fake_nd;
++};
++
++static void call_security_inode_permission(void *args)
++{
++ struct security_inode_permission_args *a = args;
++ LKTRTrace("fsuid %d\n", current->fsuid);
++ *a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
++}
++#endif
++
++static int hidden_permission(struct inode *hidden_inode, int mask,
++ struct nameidata *fake_nd, int brperm, int dlgt)
++{
++ int err, submask;
++ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
++
++ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
++ hidden_inode->i_ino, mask, brperm);
++
++ err = -EACCES;
++ if (unlikely(write_mask && IS_IMMUTABLE(hidden_inode)))
++ goto out;
++
++ /* skip hidden fs test in the case of write to ro branch */
++ submask = mask & ~MAY_APPEND;
++ if (unlikely((write_mask && !br_writable(brperm))
++ || !hidden_inode->i_op
++ || !hidden_inode->i_op->permission)) {
++ //LKTRLabel(generic_permission);
++ err = generic_permission(hidden_inode, submask, NULL);
++ } else {
++ //LKTRLabel(h_inode->permission);
++ err = hidden_inode->i_op->permission(hidden_inode, submask,
++ fake_nd);
++ TraceErr(err);
++ }
++
++#if 1
++ if (!err) {
++#ifndef CONFIG_AUFS_DLGT
++ err = security_inode_permission(hidden_inode, mask, fake_nd);
++#else
++ if (!dlgt)
++ err = security_inode_permission(hidden_inode, mask,
++ fake_nd);
++ else {
++ struct security_inode_permission_args args = {
++ .errp = &err,
++ .h_inode = hidden_inode,
++ .mask = mask,
++ .fake_nd = fake_nd
++ };
++ au_wkq_wait(call_security_inode_permission, &args,
++ /*dlgt*/1);
++ }
++#endif
++ }
++#endif
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int silly_lock(struct inode *inode, struct nameidata *nd)
++{
++ int locked = 0;
++ struct super_block *sb = inode->i_sb;
++
++ LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++#else
++ if (!nd || !nd->dentry) {
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++ } else if (nd->dentry->d_inode != inode) {
++ locked = 1;
++ /* lock child first, then parent */
++ si_read_lock(sb);
++ ii_read_lock_child(inode);
++ di_read_lock_parent(nd->dentry, 0);
++ } else {
++ locked = 2;
++ aufs_read_lock(nd->dentry, AUFS_I_RLOCK);
++ }
++#endif
++ return locked;
++}
++
++static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
++{
++ struct super_block *sb = inode->i_sb;
++
++ LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++#else
++ switch (locked) {
++ case 0:
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ break;
++ case 1:
++ di_read_unlock(nd->dentry, 0);
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ break;
++ case 2:
++ aufs_read_unlock(nd->dentry, AUFS_I_RLOCK);
++ break;
++ default:
++ BUG();
++ }
++#endif
++}
++
++static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
++{
++ int err, locked, dlgt;
++ aufs_bindex_t bindex, bend;
++ struct inode *hidden_inode;
++ struct super_block *sb;
++ struct nameidata fake_nd, *p;
++ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
++ const int nondir = !S_ISDIR(inode->i_mode);
++
++ LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
++ "nd %p{%p, %p}\n",
++ inode->i_ino, mask, nondir, write_mask,
++ nd, nd ? nd->dentry : NULL, nd ? nd->mnt : NULL);
++
++ sb = inode->i_sb;
++ locked = silly_lock(inode, nd);
++ dlgt = need_dlgt(sb);
++
++ if (nd)
++ fake_nd = *nd;
++ if (/* unlikely */(nondir || write_mask)) {
++ hidden_inode = au_h_iptr(inode);
++ DEBUG_ON(!hidden_inode
++ || ((hidden_inode->i_mode & S_IFMT)
++ != (inode->i_mode & S_IFMT)));
++ err = 0;
++ bindex = ibstart(inode);
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ /* actual test will be delegated to LSM */
++ if (IS_ERR(p))
++ DEBUG_ON(PTR_ERR(p) != -ENOENT);
++ else {
++ err = hidden_permission(hidden_inode, mask, p,
++ sbr_perm(sb, bindex), dlgt);
++ fake_dm_release(p);
++ }
++ if (write_mask && !err) {
++ err = find_rw_br(sb, bindex);
++ if (err >= 0)
++ err = 0;
++ }
++ goto out;
++ }
++
++ /* non-write to dir */
++ err = 0;
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); !err && bindex <= bend; bindex++) {
++ hidden_inode = au_h_iptr_i(inode, bindex);
++ if (!hidden_inode)
++ continue;
++ DEBUG_ON(!S_ISDIR(hidden_inode->i_mode));
++
++ p = fake_dm(&fake_nd, nd, sb, bindex);
++ /* actual test will be delegated to LSM */
++ if (IS_ERR(p))
++ DEBUG_ON(PTR_ERR(p) != -ENOENT);
++ else {
++ err = hidden_permission(hidden_inode, mask, p,
++ sbr_perm(sb, bindex), dlgt);
++ fake_dm_release(p);
++ }
++ }
++
++ out:
++ silly_unlock(locked, inode, nd);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ struct dentry *ret, *parent;
++ int err, npositive;
++ struct inode *inode;
++
++ LKTRTrace("dir %lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ DEBUG_ON(IS_ROOT(dentry));
++ IMustLock(dir);
++
++ parent = dentry->d_parent; // dget_parent()
++ aufs_read_lock(parent, !AUFS_I_RLOCK);
++ err = au_alloc_dinfo(dentry);
++ //if (LktrCond) err = -1;
++ ret = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ err = npositive = lkup_dentry(dentry, dbstart(parent), /*type*/0);
++ //err = -1;
++ ret = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ inode = NULL;
++ if (npositive) {
++ inode = au_new_inode(dentry);
++ ret = (void*)inode;
++ }
++ if (!IS_ERR(inode)) {
++#if 1
++ /* d_splice_alias() also supports d_add() */
++ ret = d_splice_alias(inode, dentry);
++ if (unlikely(IS_ERR(ret) && inode))
++ ii_write_unlock(inode);
++#else
++ d_add(dentry, inode);
++#endif
++ }
++
++ out_unlock:
++ di_write_unlock(dentry);
++ out:
++ aufs_read_unlock(parent, !AUFS_I_RLOCK);
++ TraceErrPtr(ret);
++ return ret;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * decide the branch and the parent dir where we will create a new entry.
++ * returns new bindex or an error.
++ * copyup the parent dir if needed.
++ */
++int wr_dir(struct dentry *dentry, int add_entry, struct dentry *src_dentry,
++ aufs_bindex_t force_btgt, int do_lock_srcdir)
++{
++ int err;
++ aufs_bindex_t bcpup, bstart, src_bstart;
++ struct dentry *hidden_parent;
++ struct super_block *sb;
++ struct dentry *parent, *src_parent = NULL;
++ struct inode *dir, *src_dir = NULL;
++
++ LKTRTrace("%.*s, add %d, src %p, force %d, lock_srcdir %d\n",
++ DLNPair(dentry), add_entry, src_dentry, force_btgt,
++ do_lock_srcdir);
++
++ sb = dentry->d_sb;
++ parent = dentry->d_parent; // dget_parent()
++ bcpup = bstart = dbstart(dentry);
++ if (force_btgt < 0) {
++ if (src_dentry) {
++ src_bstart = dbstart(src_dentry);
++ if (src_bstart < bstart)
++ bcpup = src_bstart;
++ }
++ if (test_ro(sb, bcpup, dentry->d_inode)) {
++ if (!add_entry)
++ di_read_lock_parent(parent, !AUFS_I_RLOCK);
++ bcpup = err = find_rw_parent_br(dentry, bcpup);
++ //bcpup = err = find_rw_br(sb, bcpup);
++ if (!add_entry)
++ di_read_unlock(parent, !AUFS_I_RLOCK);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ DEBUG_ON(bstart <= force_btgt
++ || test_ro(sb, force_btgt, dentry->d_inode));
++ bcpup = force_btgt;
++ }
++ LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
++
++ err = bcpup;
++ if (bcpup == bstart)
++ goto out; /* success */
++
++ /* copyup the new parent into the branch we process */
++ hidden_parent = au_h_dptr(dentry)->d_parent; // dget_parent()
++ if (src_dentry) {
++ src_parent = src_dentry->d_parent; // dget_parent()
++ src_dir = src_parent->d_inode;
++ if (do_lock_srcdir)
++ di_write_lock_parent2(src_parent);
++ }
++
++ dir = parent->d_inode;
++ if (add_entry) {
++ au_update_dbstart(dentry);
++ IMustLock(dir);
++ DiMustWriteLock(parent);
++ IiMustWriteLock(dir);
++ } else
++ di_write_lock_parent(parent);
++
++ err = 0;
++ if (!au_h_dptr_i(parent, bcpup))
++ err = cpup_dirs(dentry, bcpup, src_parent);
++ //err = -1;
++ if (!err && add_entry) {
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ DEBUG_ON(!hidden_parent || !hidden_parent->d_inode);
++ hi_lock_parent(hidden_parent->d_inode);
++ err = lkup_neg(dentry, bcpup);
++ //err = -1;
++ i_unlock(hidden_parent->d_inode);
++ }
++
++ if (!add_entry)
++ di_write_unlock(parent);
++ if (do_lock_srcdir)
++ di_write_unlock(src_parent);
++ if (!err)
++ err = bcpup; /* success */
++ //err = -EPERM;
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err, isdir;
++ aufs_bindex_t bstart, bcpup;
++ struct inode *hidden_inode, *inode, *dir, *h_dir, *gh_dir, *gdir;
++ struct dentry *hidden_dentry, *parent;
++ unsigned int udba;
++
++ LKTRTrace("%.*s, ia_valid 0x%x\n", DLNPair(dentry), ia->ia_valid);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ bstart = dbstart(dentry);
++ bcpup = err = wr_dir(dentry, /*add*/0, /*src_dentry*/NULL,
++ /*force_btgt*/-1, /*do_lock_srcdir*/0);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++
++ /* crazy udba locks */
++ udba = au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY);
++ parent = NULL;
++ gdir = gh_dir = dir = h_dir = NULL;
++ if ((udba || bstart != bcpup) && !IS_ROOT(dentry)) {
++ parent = dentry->d_parent; // dget_parent()
++ dir = parent->d_inode;
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ h_dir = au_h_iptr_i(dir, bcpup);
++ }
++ if (parent) {
++ if (unlikely(udba && !IS_ROOT(parent))) {
++ gdir = parent->d_parent->d_inode; // dget_parent()
++ ii_read_lock_parent2(gdir);
++ gh_dir = au_h_iptr_i(gdir, bcpup);
++ hgdir_lock(gh_dir, gdir, bcpup);
++ }
++ hdir_lock(h_dir, dir, bcpup);
++ }
++
++ isdir = S_ISDIR(inode->i_mode);
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++#define HiLock(bindex) do {\
++ if (!isdir) \
++ hi_lock_child(hidden_inode); \
++ else \
++ hdir2_lock(hidden_inode, inode, bindex); \
++ } while (0)
++#define HiUnlock(bindex) do {\
++ if (!isdir) \
++ i_unlock(hidden_inode); \
++ else \
++ hdir_unlock(hidden_inode, inode, bindex); \
++ } while (0)
++
++ if (bstart != bcpup) {
++ loff_t size = -1;
++
++ if ((ia->ia_valid & ATTR_SIZE)
++ && ia->ia_size < i_size_read(inode)) {
++ size = ia->ia_size;
++ ia->ia_valid &= ~ATTR_SIZE;
++ }
++ HiLock(bstart);
++ err = sio_cpup_simple(dentry, bcpup, size,
++ au_flags_cpup(CPUP_DTIME, parent));
++ //err = -1;
++ HiUnlock(bstart);
++ if (unlikely(err || !ia->ia_valid))
++ goto out_unlock;
++
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++ }
++
++ HiLock(bcpup);
++ err = vfsub_notify_change(hidden_dentry, ia, need_dlgt(dentry->d_sb));
++ //err = -1;
++ if (!err)
++ au_cpup_attr_changable(inode);
++ HiUnlock(bcpup);
++#undef HiLock
++#undef HiUnlock
++
++ out_unlock:
++ if (parent) {
++ hdir_unlock(h_dir, dir, bcpup);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ }
++ if (unlikely(gdir)) {
++ hdir_unlock(gh_dir, gdir, bcpup);
++ ii_read_unlock(gdir);
++ }
++ out:
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int hidden_readlink(struct dentry *dentry, int bindex,
++ char __user * buf, int bufsiz)
++{
++ struct super_block *sb;
++ struct dentry *hidden_dentry;
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (unlikely(!hidden_dentry->d_inode->i_op
++ || !hidden_dentry->d_inode->i_op->readlink))
++ return -EINVAL;
++
++ sb = dentry->d_sb;
++ if (!test_ro(sb, bindex, dentry->d_inode)) {
++ touch_atime(sbr_mnt(sb, bindex), hidden_dentry);
++ dentry->d_inode->i_atime = hidden_dentry->d_inode->i_atime;
++ }
++ return hidden_dentry->d_inode->i_op->readlink
++ (hidden_dentry, buf, bufsiz);
++}
++
++static int aufs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
++{
++ int err;
++
++ LKTRTrace("%.*s, %d\n", DLNPair(dentry), bufsiz);
++
++ aufs_read_lock(dentry, AUFS_I_RLOCK);
++ err = hidden_readlink(dentry, dbstart(dentry), buf, bufsiz);
++ //err = -1;
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++ TraceErr(err);
++ return err;
++}
++
++static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ int err;
++ char *buf;
++ mm_segment_t old_fs;
++
++ LKTRTrace("%.*s, nd %.*s\n", DLNPair(dentry), DLNPair(nd->dentry));
++
++ err = -ENOMEM;
++ buf = __getname();
++ //buf = NULL;
++ if (unlikely(!buf))
++ goto out;
++
++ aufs_read_lock(dentry, AUFS_I_RLOCK);
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = hidden_readlink(dentry, dbstart(dentry), (char __user *)buf,
++ PATH_MAX);
++ //err = -1;
++ set_fs(old_fs);
++ aufs_read_unlock(dentry, AUFS_I_RLOCK);
++
++ if (err >= 0) {
++ buf[err] = 0;
++ /* will be freed by put_link */
++ nd_set_link(nd, buf);
++ return NULL; /* success */
++ }
++ __putname(buf);
++
++ out:
++ path_release(nd);
++ TraceErr(err);
++ return ERR_PTR(err);
++}
++
++static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
++ void *cookie)
++{
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ __putname(nd_get_link(nd));
++}
++
++/* ---------------------------------------------------------------------- */
++#if 0 // comment
++struct inode_operations {
++ int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
++ struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
++ int (*link) (struct dentry *,struct inode *,struct dentry *);
++ int (*unlink) (struct inode *,struct dentry *);
++ int (*symlink) (struct inode *,struct dentry *,const char *);
++ int (*mkdir) (struct inode *,struct dentry *,int);
++ int (*rmdir) (struct inode *,struct dentry *);
++ int (*mknod) (struct inode *,struct dentry *,int,dev_t);
++ int (*rename) (struct inode *, struct dentry *,
++ struct inode *, struct dentry *);
++ int (*readlink) (struct dentry *, char __user *,int);
++ void * (*follow_link) (struct dentry *, struct nameidata *);
++ void (*put_link) (struct dentry *, struct nameidata *, void *);
++ void (*truncate) (struct inode *);
++ int (*permission) (struct inode *, int, struct nameidata *);
++ int (*setattr) (struct dentry *, struct iattr *);
++ int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
++ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
++ ssize_t (*listxattr) (struct dentry *, char *, size_t);
++ int (*removexattr) (struct dentry *, const char *);
++ void (*truncate_range)(struct inode *, loff_t, loff_t);
++};
++#endif
++
++struct inode_operations aufs_symlink_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++ .readlink = aufs_readlink,
++ .follow_link = aufs_follow_link,
++ .put_link = aufs_put_link
++};
++
++//i_op_add.c
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd);
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry);
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++
++//i_op_del.c
++int aufs_unlink(struct inode *dir, struct dentry *dentry);
++int aufs_rmdir(struct inode *dir, struct dentry *dentry);
++
++// i_op_ren.c
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry);
++
++struct inode_operations aufs_dir_iop = {
++ .create = aufs_create,
++ .lookup = aufs_lookup,
++ .link = aufs_link,
++ .unlink = aufs_unlink,
++ .symlink = aufs_symlink,
++ .mkdir = aufs_mkdir,
++ .rmdir = aufs_rmdir,
++ .mknod = aufs_mknod,
++ .rename = aufs_rename,
++
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++#if 0 // xattr
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr
++#endif
++};
++
++struct inode_operations aufs_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++
++#if 0 // xattr
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr
++#endif
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_add.c linux-2.6.22.1/fs/aufs/i_op_add.c
+--- linux-2.6.22.1.oorig/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/i_op_add.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,621 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_add.c,v 1.37 2007/05/07 03:46:08 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++/*
++ * final procedure of adding a new entry, except link(2).
++ * remove whiteout, instantiate, copyup the parent dir's times and size
++ * and update version.
++ * if it failed, re-create the removed whiteout.
++ */
++static int epilog(struct dentry *wh_dentry, struct dentry *dentry)
++{
++ int err, rerr;
++ aufs_bindex_t bwh;
++ struct inode *inode, *dir;
++ struct dentry *wh;
++ struct lkup_args lkup;
++
++ LKTRTrace("wh %p, %.*s\n", wh_dentry, DLNPair(dentry));
++
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ bwh = -1;
++ if (wh_dentry) {
++ bwh = dbwh(dentry);
++ err = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode,
++ wh_dentry, dentry, lkup.dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ }
++
++ inode = au_new_inode(dentry);
++ //inode = ERR_PTR(-1);
++ if (!IS_ERR(inode)) {
++ d_instantiate(dentry, inode);
++ dir = dentry->d_parent->d_inode;
++ /* or always cpup dir mtime? */
++ if (ibstart(dir) == dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++ return 0; /* success */
++ }
++
++ err = PTR_ERR(inode);
++ if (!wh_dentry)
++ goto out;
++
++ /* revert */
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bwh);
++ wh = simple_create_wh(dentry, bwh, wh_dentry->d_parent, &lkup);
++ //wh = ERR_PTR(-1);
++ rerr = PTR_ERR(wh);
++ if (!IS_ERR(wh)) {
++ dput(wh);
++ goto out;
++ }
++ IOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * initial procedure of adding a new entry.
++ * prepare writable branch and the parent dir, lock it,
++ * lookup whiteout for the new entry.
++ */
++static struct dentry *
++lock_hdir_lkup_wh(struct dentry *dentry, struct dtime *dt,
++ struct dentry *src_dentry, int do_lock_srcdir)
++{
++ struct dentry *wh_dentry, *parent, *hidden_parent;
++ int err;
++ aufs_bindex_t bstart, bcpup;
++ struct inode *dir, *h_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, src %p\n", DLNPair(dentry), src_dentry);
++
++ parent = dentry->d_parent;
++ bstart = dbstart(dentry);
++ bcpup = err = wr_dir(dentry, 1, src_dentry, -1, do_lock_srcdir);
++ //err = -1;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ dir = parent->d_inode;
++ hidden_parent = au_h_dptr_i(parent, bcpup);
++ h_dir = hidden_parent->d_inode;
++ hdir_lock(h_dir, dir, bcpup);
++ if (dt)
++ dtime_store(dt, parent, hidden_parent);
++ if (/* bcpup != bstart || */ bcpup != dbwh(dentry))
++ return NULL; /* success */
++
++ lkup.nfsmnt = au_nfsmnt(parent->d_sb, bcpup);
++ lkup.dlgt = need_dlgt(parent->d_sb);
++ wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, &lkup);
++ //wh_dentry = ERR_PTR(-1);
++ if (IS_ERR(wh_dentry))
++ hdir_unlock(h_dir, dir, bcpup);
++
++ out:
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++enum {Mknod, Symlink, Creat};
++struct simple_arg {
++ int type;
++ union {
++ struct {
++ int mode;
++ struct nameidata *nd;
++ } c;
++ struct {
++ const char *symname;
++ } s;
++ struct {
++ int mode;
++ dev_t dev;
++ } m;
++ } u;
++};
++
++static int add_simple(struct inode *dir, struct dentry *dentry,
++ struct simple_arg *arg)
++{
++ int err, dlgt;
++ struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent;
++ struct inode *hidden_dir;
++ struct dtime dt;
++
++ LKTRTrace("type %d, %.*s\n", arg->type, DLNPair(dentry));
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
++ /*do_lock_srcdir*/0);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ dlgt = need_dlgt(dir->i_sb);
++
++#if 1 // partial testing
++ switch (arg->type) {
++ case Creat:
++#if 0
++ if (arg->u.c.nd) {
++ struct nameidata fake_nd;
++ fake_nd = *arg->u.c.nd;
++ fake_nd.dentry = dget(hidden_parent);
++ fake_nd.mnt = sbr_mnt(dentry->d_sb, dbstart(dentry));
++ mntget(fake_nd.mnt);
++ err = vfsub_create(hidden_dir, hidden_dentry,
++ arg->u.c.mode, &fake_nd, dlgt);
++ path_release(&fake_nd);
++ } else
++#endif
++ err = vfsub_create(hidden_dir, hidden_dentry,
++ arg->u.c.mode, NULL, dlgt);
++ break;
++ case Symlink:
++ err = vfsub_symlink(hidden_dir, hidden_dentry,
++ arg->u.s.symname, S_IALLUGO, dlgt);
++ break;
++ case Mknod:
++ err = vfsub_mknod(hidden_dir, hidden_dentry,
++ arg->u.m.mode, arg->u.m.dev, dlgt);
++ break;
++ default:
++ BUG();
++ }
++#else
++ err = -1;
++#endif
++ if (!err)
++ err = epilog(wh_dentry, dentry);
++ //err = -1;
++
++ /* revert */
++ if (unlikely(err && hidden_dentry->d_inode)) {
++ int rerr;
++ rerr = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
++ //rerr = -1;
++ if (rerr) {
++ IOErr("%.*s revert failure(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++ d_drop(dentry);
++ }
++
++ hdir_unlock(hidden_dir, dir, dbstart(dentry));
++ dput(wh_dentry);
++
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++ struct simple_arg arg = {
++ .type = Mknod,
++ .u.m = {.mode = mode, .dev = dev}
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++ struct simple_arg arg = {
++ .type = Symlink,
++ .u.s.symname = symname
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ struct simple_arg arg = {
++ .type = Creat,
++ .u.c = {.mode = mode, .nd = nd}
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct link_arg {
++ aufs_bindex_t bdst, bsrc;
++ int issamedir, dlgt;
++ struct dentry *src_parent, *parent, *hidden_dentry;
++ struct inode *hidden_dir, *inode;
++};
++
++static int cpup_before_link(struct dentry *src_dentry, struct inode *dir,
++ struct link_arg *a)
++{
++ int err;
++ unsigned int flags;
++ struct inode *hi, *hdir = NULL, *src_dir;
++
++ TraceEnter();
++
++ err = 0;
++ flags = au_flags_cpup(CPUP_DTIME, a->parent);
++ src_dir = a->src_parent->d_inode;
++ if (!a->issamedir) {
++ // todo: dead lock?
++ di_read_lock_parent2(a->src_parent, AUFS_I_RLOCK);
++ // this temporary unlock/lock is safe
++ hdir_unlock(a->hidden_dir, dir, a->bdst);
++ err = test_and_cpup_dirs(src_dentry, a->bdst, a->parent);
++ //err = -1;
++ if (!err) {
++ hdir = au_h_iptr_i(src_dir, a->bdst);
++ hdir_lock(hdir, src_dir, a->bdst);
++ flags = au_flags_cpup(CPUP_DTIME, a->src_parent);
++ }
++ }
++
++ if (!err) {
++ hi = au_h_dptr(src_dentry)->d_inode;
++ hi_lock_child(hi);
++ err = sio_cpup_simple(src_dentry, a->bdst, -1, flags);
++ //err = -1;
++ i_unlock(hi);
++ }
++
++ if (!a->issamedir) {
++ if (hdir)
++ hdir_unlock(hdir, src_dir, a->bdst);
++ hdir_lock(a->hidden_dir, dir, a->bdst);
++ di_read_unlock(a->src_parent, AUFS_I_RLOCK);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int cpup_or_link(struct dentry *src_dentry, struct link_arg *a)
++{
++ int err;
++ struct inode *inode, *h_inode, *h_dst_inode;
++ struct dentry *h_dentry;
++ aufs_bindex_t bstart;
++ struct super_block *sb;
++
++ TraceEnter();
++
++ sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ h_dentry = au_h_dptr(src_dentry);
++ h_inode = h_dentry->d_inode;
++ bstart = ibstart(inode);
++ h_dst_inode = NULL;
++ if (bstart <= a->bdst)
++ h_dst_inode = au_h_iptr_i(inode, a->bdst);
++
++ if (!h_dst_inode) {
++ /* copyup src_dentry as the name of dentry. */
++ set_dbstart(src_dentry, a->bdst);
++ set_h_dptr(src_dentry, a->bdst, dget(a->hidden_dentry));
++ hi_lock_child(h_inode);
++ err = sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
++ au_flags_cpup(!CPUP_DTIME, a->parent));
++ //err = -1;
++ i_unlock(h_inode);
++ set_h_dptr(src_dentry, a->bdst, NULL);
++ set_dbstart(src_dentry, a->bsrc);
++ } else {
++ /* the inode of src_dentry already exists on a.bdst branch */
++ h_dentry = d_find_alias(h_dst_inode);
++ if (h_dentry) {
++ err = vfsub_link(h_dentry, a->hidden_dir,
++ a->hidden_dentry, a->dlgt);
++ dput(h_dentry);
++ } else {
++ IOErr("no dentry found for i%lu on b%d\n",
++ h_dst_inode->i_ino, a->bdst);
++ err = -EIO;
++ }
++ }
++
++ if (!err)
++ append_plink(sb, a->inode, a->hidden_dentry, a->bdst);
++
++ TraceErr(err);
++ return err;
++}
++
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err, rerr;
++ struct dentry *hidden_parent, *wh_dentry, *hidden_src_dentry;
++ struct dtime dt;
++ struct link_arg a;
++ struct super_block *sb;
++
++ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
++ DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ IMustLock(src_dentry->d_inode);
++
++ aufs_read_and_write_lock2(dentry, src_dentry, /*isdir*/0);
++ a.src_parent = src_dentry->d_parent;
++ a.parent = dentry->d_parent;
++ a.issamedir = (a.src_parent == a.parent);
++ di_write_lock_parent(a.parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, !a.issamedir);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ a.inode = src_dentry->d_inode;
++ a.hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = a.hidden_dentry->d_parent;
++ a.hidden_dir = hidden_parent->d_inode;
++ IMustLock(a.hidden_dir);
++
++ err = 0;
++ sb = dentry->d_sb;
++ a.dlgt = need_dlgt(sb);
++
++ //todo: minor optimize, their sb may be same while their bindex differs.
++ a.bsrc = dbstart(src_dentry);
++ a.bdst = dbstart(dentry);
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
++ /*
++ * copyup src_dentry to the branch we process,
++ * and then link(2) to it.
++ * gave up 'pseudo link by cpup' approach,
++ * since nlink may be one and some applications will not work.
++ */
++ if (a.bdst < a.bsrc
++ /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
++ err = cpup_before_link(src_dentry, dir, &a);
++ if (!err) {
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ err = vfsub_link(hidden_src_dentry, a.hidden_dir,
++ a.hidden_dentry, a.dlgt);
++ //err = -1;
++ }
++ } else {
++ if (a.bdst < a.bsrc
++ /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
++ err = cpup_or_link(src_dentry, &a);
++ else {
++ hidden_src_dentry = au_h_dptr(src_dentry);
++ err = vfsub_link(hidden_src_dentry, a.hidden_dir,
++ a.hidden_dentry, a.dlgt);
++ //err = -1;
++ }
++ }
++ if (unlikely(err))
++ goto out_unlock;
++ if (wh_dentry) {
++ err = au_unlink_wh_dentry(a.hidden_dir, wh_dentry, dentry,
++ a.dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_revert;
++ }
++
++ dir->i_version++;
++ if (ibstart(dir) == dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ if (!d_unhashed(a.hidden_dentry)
++ /* || hidden_old_inode->i_nlink <= nlink */
++ /* || SB_NFS(hidden_src_dentry->d_sb) */) {
++ dentry->d_inode = igrab(a.inode);
++ d_instantiate(dentry, a.inode);
++ a.inode->i_nlink++;
++ a.inode->i_ctime = dir->i_ctime;
++ } else
++ /* nfs case (< 2.6.15) */
++ d_drop(dentry);
++#if 0
++ au_debug_on();
++ DbgInode(a.inode);
++ au_debug_off();
++ {
++ aufs_bindex_t i;
++ for (i = ibstart(a.inode); i <= ibend(a.inode); i++) {
++ struct xino xino;
++ struct inode *hi;
++ hi = au_h_iptr_i(a.inode, i);
++ if (hi) {
++ xino_read(sb, i, hi->i_ino, &xino);
++ Dbg("hi%lu, i%lu\n", hi->i_ino, xino.ino);
++ }
++ }
++ }
++#endif
++ goto out_unlock; /* success */
++
++ out_revert:
++#if 0 // remove
++ if (d_unhashed(a.hidden_dentry)) {
++ /* hardlink on nfs (< 2.6.15) */
++ struct dentry *d;
++ const struct qstr *name = &a.hidden_dentry->d_name;
++ DEBUG_ON(a.hidden_dentry->d_parent->d_inode != a.hidden_dir);
++ // do not superio.
++ d = lkup_one(name->name, a.hidden_dentry->d_parent, name->len,
++ au_nfsmnt(sb, a.bdst)??, need_dlgt(sb));
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out_rerr;
++ dput(a.hidden_dentry);
++ a.hidden_dentry = d;
++ DEBUG_ON(!d->d_inode);
++ }
++#endif
++ rerr = vfsub_unlink(a.hidden_dir, a.hidden_dentry, a.dlgt);
++ //rerr = -1;
++ if (!rerr)
++ goto out_dt;
++// out_rerr:
++ IOErr("%.*s reverting failed(%d, %d)\n", DLNPair(dentry), err, rerr);
++ err = -EIO;
++ out_dt:
++ d_drop(dentry);
++ dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
++ out_unlock:
++ hdir_unlock(a.hidden_dir, dir, a.bdst);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(a.parent);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err, rerr, diropq, dlgt;
++ struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent,
++ *opq_dentry;
++ struct inode *hidden_dir, *hidden_inode;
++ struct dtime dt;
++ aufs_bindex_t bindex;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s, mode 0%o\n", dir->i_ino, DLNPair(dentry), mode);
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
++ /*do_lock_srcdir*/0);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dentry->d_sb;
++ bindex = dbstart(dentry);
++ hidden_dentry = au_h_dptr(dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ dlgt = need_dlgt(sb);
++
++ err = vfsub_mkdir(hidden_dir, hidden_dentry, mode, dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_unlock;
++ hidden_inode = hidden_dentry->d_inode;
++
++ /* make the dir opaque */
++ diropq = 0;
++ if (unlikely(wh_dentry || au_flag_test(sb, AuFlag_ALWAYS_DIROPQ))) {
++ hi_lock_child(hidden_inode);
++ opq_dentry = create_diropq(dentry, bindex, dlgt);
++ //opq_dentry = ERR_PTR(-1);
++ i_unlock(hidden_inode);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out_dir;
++ dput(opq_dentry);
++ diropq = 1;
++ }
++
++ err = epilog(wh_dentry, dentry);
++ //err = -1;
++ if (!err) {
++ dir->i_nlink++;
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (unlikely(diropq)) {
++ LKTRLabel(revert opq);
++ hi_lock_child(hidden_inode);
++ rerr = remove_diropq(dentry, bindex, dlgt);
++ //rerr = -1;
++ i_unlock(hidden_inode);
++ if (rerr) {
++ IOErr("%.*s reverting diropq failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ }
++
++ out_dir:
++ LKTRLabel(revert dir);
++ rerr = vfsub_rmdir(hidden_dir, hidden_dentry, dlgt);
++ //rerr = -1;
++ if (rerr) {
++ IOErr("%.*s reverting dir failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ d_drop(dentry);
++ dtime_revert(&dt, /*fake flag*/CPUP_LOCKED_GHDIR);
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_del.c linux-2.6.22.1/fs/aufs/i_op_del.c
+--- linux-2.6.22.1.oorig/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/i_op_del.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,414 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_del.c,v 1.35 2007/05/14 03:41:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++/* returns,
++ * 0: wh is unnecessary
++ * plus: wh is necessary
++ * minus: error
++ */
++int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dentry *locked)
++{
++ int need_wh, err;
++ aufs_bindex_t bstart;
++ struct dentry *hidden_dentry;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
++ DLNPair(dentry), isdir, *bcpup, locked);
++ sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
++ hidden_dentry = au_h_dptr(dentry);
++ if (*bcpup < 0) {
++ *bcpup = bstart;
++ if (test_ro(sb, bstart, dentry->d_inode)) {
++ *bcpup = err = find_rw_parent_br(dentry, bstart);
++ //*bcpup = err = find_rw_br(sb, bstart);
++ //err = -1;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ /* braces are added to stop a warning */
++ DEBUG_ON(bstart < *bcpup
++ || test_ro(sb, *bcpup, dentry->d_inode));
++ }
++ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
++
++ if (*bcpup != bstart) {
++ err = cpup_dirs(dentry, *bcpup, locked);
++ //err = -1;
++ if (unlikely(err))
++ goto out;
++ need_wh = 1;
++ } else {
++ //struct nameidata nd;
++ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
++ old_bend = dbend(dentry);
++ if (isdir) {
++ bdiropq = dbdiropq(dentry);
++ set_dbdiropq(dentry, -1);
++ }
++ err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0);
++ //err = -1;
++ if (isdir)
++ set_dbdiropq(dentry, bdiropq);
++ if (unlikely(err < 0))
++ goto out;
++ new_bend = dbend(dentry);
++ if (!need_wh && old_bend != new_bend) {
++ set_h_dptr(dentry, new_bend, NULL);
++ set_dbend(dentry, old_bend);
++#if 0
++ } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) {
++ LKTRTrace("negative\n");
++ set_h_dptr(dentry, new_bend, NULL);
++ set_dbend(dentry, old_bend);
++ need_wh = 0;
++#endif
++ }
++ }
++ LKTRTrace("need_wh %d\n", need_wh);
++ err = need_wh;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static struct dentry *
++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dtime *dt)
++{
++ struct dentry *wh_dentry;
++ int err, need_wh;
++ struct dentry *hidden_parent, *parent;
++ struct inode *dir, *h_dir;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
++
++ err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
++ //err = -1;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ parent = dentry->d_parent;
++ dir = parent->d_inode;
++ hidden_parent = au_h_dptr_i(parent, *bcpup);
++ h_dir = hidden_parent->d_inode;
++ hdir_lock(h_dir, dir, *bcpup);
++ dtime_store(dt, parent, hidden_parent);
++ if (!need_wh)
++ return NULL; /* success, no need to create whiteout */
++
++ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
++ lkup.dlgt = need_dlgt(dentry->d_sb);
++ wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
++ //wh_dentry = ERR_PTR(-1);
++ if (!IS_ERR(wh_dentry))
++ goto out; /* success */
++ /* returns with the parent is locked and wh_dentry is DGETed */
++
++ hdir_unlock(h_dir, dir, *bcpup);
++
++ out:
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
++ struct aufs_nhash *whlist, struct inode *dir)
++{
++ int rmdir_later, err;
++ struct dentry *hidden_dentry;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++
++ err = rename_whtmp(dentry, bindex);
++ //err = -1;
++#if 0
++ //todo: bug
++ if (unlikely(err)) {
++ au_direval_inc(dentry->d_parent);
++ return err;
++ }
++#endif
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!au_is_nfs(hidden_dentry->d_sb)) {
++ const int dirwh = stosi(dentry->d_sb)->si_dirwh;
++ rmdir_later = (dirwh <= 1);
++ if (!rmdir_later)
++ rmdir_later = is_longer_wh(whlist, bindex, dirwh);
++ if (rmdir_later)
++ return rmdir_later;
++ }
++
++ err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
++ //err = -1;
++ if (unlikely(err)) {
++ IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
++ DLNPair(hidden_dentry), bindex, err);
++ err = 0;
++ }
++ TraceErr(err);
++ return err;
++}
++
++static void epilog(struct inode *dir, struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ d_drop(dentry);
++ dentry->d_inode->i_ctime = dir->i_ctime;
++ if (atomic_read(&dentry->d_count) == 1) {
++ set_h_dptr(dentry, dbstart(dentry), NULL);
++ au_update_dbstart(dentry);
++ }
++ if (ibstart(dir) == bindex)
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++}
++
++static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
++ aufs_bindex_t bwh, struct dtime *dt, int dlgt)
++{
++ int rerr;
++
++ rerr = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode, wh_dentry,
++ dentry, dlgt);
++ //rerr = -1;
++ if (!rerr) {
++ set_dbwh(dentry, bwh);
++ dtime_revert(dt, !CPUP_LOCKED_GHDIR);
++ return 0;
++ }
++
++ IOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ DLNPair(dentry), err, rerr);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err, dlgt;
++ struct inode *inode, *hidden_dir;
++ struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
++ struct dtime dt;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; // possible?
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++
++ bstart = dbstart(dentry);
++ bwh = dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dir->i_sb;
++ dlgt = need_dlgt(sb);
++ hidden_dentry = au_h_dptr(dentry);
++ dget(hidden_dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++
++ if (bindex == bstart) {
++ err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
++ //err = -1;
++ } else {
++ DEBUG_ON(!wh_dentry);
++ hidden_parent = wh_dentry->d_parent;
++ DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ err = 0;
++ }
++
++ if (!err) {
++ inode->i_nlink--;
++ epilog(dir, dentry, bindex);
++#if 0
++ xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
++ /* ignore this error */
++#endif
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (wh_dentry) {
++ int rerr;
++ rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ dput(hidden_dentry);
++ out:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ TraceErr(err);
++ return err;
++}
++
++int aufs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err, rmdir_later;
++ struct inode *inode, *hidden_dir;
++ struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
++ struct dtime dt;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct rmdir_whtmp_arg *arg;
++ struct aufs_nhash *whlist;
++ struct super_block *sb;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; // possible?
++ IMustLock(inode);
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++
++ err = -ENOMEM;
++ arg = kmalloc(sizeof(*arg), GFP_KERNEL);
++ //arg = NULL;
++ if (unlikely(!arg))
++ goto out_whlist;
++
++ aufs_read_lock(dentry, AUFS_D_WLOCK);
++ parent = dentry->d_parent;
++ di_write_lock_parent(parent);
++ err = test_empty(dentry, whlist);
++ //err = -1;
++ if (unlikely(err))
++ goto out_arg;
++
++ bstart = dbstart(dentry);
++ bwh = dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt);
++ //wh_dentry = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_arg;
++
++ hidden_dentry = au_h_dptr(dentry);
++ dget(hidden_dentry);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++
++ rmdir_later = 0;
++ if (bindex == bstart) {
++ IMustLock(hidden_dir);
++ err = renwh_and_rmdir(dentry, bstart, whlist, dir);
++ //err = -1;
++ if (err > 0) {
++ rmdir_later = err;
++ err = 0;
++ }
++ } else {
++ DEBUG_ON(!wh_dentry);
++ hidden_parent = wh_dentry->d_parent;
++ DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ err = 0;
++ }
++
++ sb = dentry->d_sb;
++ if (!err) {
++ //aufs_bindex_t bi, bend;
++
++ au_reset_hinotify(inode, /*flags*/0);
++ inode->i_nlink = 0;
++ set_dbdiropq(dentry, -1);
++ epilog(dir, dentry, bindex);
++
++ if (rmdir_later) {
++ kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
++ inode, arg);
++ arg = NULL;
++ }
++
++#if 0
++ bend = dbend(dentry);
++ for (bi = bstart; bi <= bend; bi++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(dentry, bi);
++ if (hd && hd->d_inode)
++ xino_write0(sb, bi, hd->d_inode->i_ino);
++ /* ignore this error */
++ }
++#endif
++
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ LKTRLabel(revert);
++ if (wh_dentry) {
++ int rerr;
++ rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
++ need_dlgt(sb));
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ hdir_unlock(hidden_dir, dir, bindex);
++ dput(wh_dentry);
++ dput(hidden_dentry);
++ out_arg:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AUFS_D_WLOCK);
++ kfree(arg);
++ out_whlist:
++ nhash_del(whlist);
++ out:
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_ren.c linux-2.6.22.1/fs/aufs/i_op_ren.c
+--- linux-2.6.22.1.oorig/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/i_op_ren.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,637 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: i_op_ren.c,v 1.39 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++#include "aufs.h"
++
++enum {SRC, DST};
++struct rename_args {
++ struct dentry *hidden_dentry[2], *parent[2], *hidden_parent[2];
++ struct aufs_nhash whlist;
++ aufs_bindex_t btgt, bstart[2];
++ struct super_block *sb;
++
++ unsigned int isdir:1;
++ unsigned int issamedir:1;
++ unsigned int whsrc:1;
++ unsigned int whdst:1;
++ unsigned int dlgt:1;
++} __attribute__((aligned(sizeof(long))));
++
++static int do_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry,
++ struct rename_args *a)
++{
++ int err, need_diropq, bycpup, rerr;
++ struct rmdir_whtmp_arg *tharg;
++ struct dentry *wh_dentry[2], *hidden_dst, *hg_parent;
++ struct inode *hidden_dir[2];
++ aufs_bindex_t bindex, bend;
++ unsigned int flags;
++ struct lkup_args lkup = {.dlgt = a->dlgt};
++
++ LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
++ "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
++ "flags{%d, %d, %d, %d}\n",
++ DLNPair(a->parent[SRC]), DLNPair(src_dentry),
++ DLNPair(a->parent[DST]), DLNPair(dentry),
++ a->hidden_dentry[SRC], a->hidden_dentry[DST],
++ a->hidden_parent[SRC], a->hidden_parent[DST],
++ &a->whlist, a->btgt,
++ a->bstart[SRC], a->bstart[DST],
++ a->isdir, a->issamedir, a->whsrc, a->whdst);
++ hidden_dir[SRC] = a->hidden_parent[SRC]->d_inode;
++ hidden_dir[DST] = a->hidden_parent[DST]->d_inode;
++ IMustLock(hidden_dir[SRC]);
++ IMustLock(hidden_dir[DST]);
++
++ /* prepare workqueue arg */
++ hidden_dst = NULL;
++ tharg = NULL;
++ if (a->isdir && a->hidden_dentry[DST]->d_inode) {
++ err = -ENOMEM;
++ tharg = kmalloc(sizeof(*tharg), GFP_KERNEL);
++ //tharg = NULL;
++ if (unlikely(!tharg))
++ goto out;
++ hidden_dst = dget(a->hidden_dentry[DST]);
++ }
++
++ wh_dentry[SRC] = wh_dentry[DST] = NULL;
++ lkup.nfsmnt = au_nfsmnt(a->sb, a->btgt);
++ /* create whiteout for src_dentry */
++ if (a->whsrc) {
++ wh_dentry[SRC] = simple_create_wh(src_dentry, a->btgt,
++ a->hidden_parent[SRC], &lkup);
++ //wh_dentry[SRC] = ERR_PTR(-1);
++ err = PTR_ERR(wh_dentry[SRC]);
++ if (IS_ERR(wh_dentry[SRC]))
++ goto out_tharg;
++ }
++
++ /* lookup whiteout for dentry */
++ if (a->whdst) {
++ struct dentry *d;
++ d = lkup_wh(a->hidden_parent[DST], &dentry->d_name, &lkup);
++ //d = ERR_PTR(-1);
++ err = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out_whsrc;
++ if (!d->d_inode)
++ dput(d);
++ else
++ wh_dentry[DST] = d;
++ }
++
++ /* rename dentry to tmpwh */
++ if (tharg) {
++ err = rename_whtmp(dentry, a->btgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_whdst;
++ set_h_dptr(dentry, a->btgt, NULL);
++ err = lkup_neg(dentry, a->btgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_whtmp;
++ a->hidden_dentry[DST] = au_h_dptr_i(dentry, a->btgt);
++ }
++
++ /* cpup src */
++ if (a->hidden_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
++ flags = au_flags_cpup(!CPUP_DTIME, a->parent[SRC]);
++ hg_parent = a->hidden_parent[SRC]->d_parent;
++ if (!(flags & CPUP_LOCKED_GHDIR)
++ && hg_parent == a->hidden_parent[DST])
++ flags |= CPUP_LOCKED_GHDIR;
++
++ hi_lock_child(a->hidden_dentry[SRC]->d_inode);
++ err = sio_cpup_simple(src_dentry, a->btgt, -1, flags);
++ //err = -1; // untested dir
++ i_unlock(a->hidden_dentry[SRC]->d_inode);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++
++#if 0
++ /* clear the target ino in xino */
++ LKTRTrace("dir %d, dst inode %p\n", a->isdir, a->hidden_dentry[DST]->d_inode);
++ if (a->isdir && a->hidden_dentry[DST]->d_inode) {
++ Dbg("here\n");
++ err = xino_write(a->sb, a->btgt,
++ a->hidden_dentry[DST]->d_inode->i_ino, 0);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++#endif
++
++ /* rename by vfs_rename or cpup */
++ need_diropq = a->isdir
++ && (wh_dentry[DST]
++ || dbdiropq(dentry) == a->btgt
++ || au_flag_test(a->sb, AuFlag_ALWAYS_DIROPQ));
++ bycpup = 0;
++ if (dbstart(src_dentry) == a->btgt) {
++ if (need_diropq && dbdiropq(src_dentry) == a->btgt)
++ need_diropq = 0;
++ err = vfsub_rename(hidden_dir[SRC], au_h_dptr(src_dentry),
++ hidden_dir[DST], a->hidden_dentry[DST],
++ a->dlgt);
++ //err = -1;
++ } else {
++ bycpup = 1;
++ flags = au_flags_cpup(!CPUP_DTIME, a->parent[DST]);
++ hg_parent = a->hidden_parent[DST]->d_parent;
++ if (!(flags & CPUP_LOCKED_GHDIR)
++ && hg_parent == a->hidden_parent[SRC])
++ flags |= CPUP_LOCKED_GHDIR;
++
++ hi_lock_child(a->hidden_dentry[SRC]->d_inode);
++ set_dbstart(src_dentry, a->btgt);
++ set_h_dptr(src_dentry, a->btgt, dget(a->hidden_dentry[DST]));
++ //DbgDentry(src_dentry);
++ //DbgInode(src_dentry->d_inode);
++ err = sio_cpup_single(src_dentry, a->btgt, a->bstart[SRC], -1,
++ flags);
++ //err = -1; // untested dir
++ if (unlikely(err)) {
++ set_h_dptr(src_dentry, a->btgt, NULL);
++ set_dbstart(src_dentry, a->bstart[SRC]);
++ }
++ i_unlock(a->hidden_dentry[SRC]->d_inode);
++ }
++ if (unlikely(err))
++ goto out_whtmp;
++
++ /* make dir opaque */
++ if (need_diropq) {
++ struct dentry *diropq;
++ struct inode *h_inode;
++
++ h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
++ hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
++ diropq = create_diropq(src_dentry, a->btgt, a->dlgt);
++ //diropq = ERR_PTR(-1);
++ hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
++ err = PTR_ERR(diropq);
++ if (IS_ERR(diropq))
++ goto out_rename;
++ dput(diropq);
++ }
++
++ /* remove whiteout for dentry */
++ if (wh_dentry[DST]) {
++ err = au_unlink_wh_dentry(hidden_dir[DST], wh_dentry[DST],
++ dentry, a->dlgt);
++ //err = -1;
++ if (unlikely(err))
++ goto out_diropq;
++ }
++
++ /* remove whtmp */
++ if (tharg) {
++ if (au_is_nfs(hidden_dst->d_sb)
++ || !is_longer_wh(&a->whlist, a->btgt,
++ stosi(a->sb)->si_dirwh)) {
++ err = rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
++ dentry->d_inode);
++ if (unlikely(err))
++ Warn("failed removing whtmp dir %.*s (%d), "
++ "ignored.\n", DLNPair(hidden_dst), err);
++ } else {
++ kick_rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
++ dentry->d_inode, tharg);
++ dput(hidden_dst);
++ tharg = NULL;
++ }
++ }
++ err = 0;
++ goto out_success;
++
++#define RevertFailure(fmt, args...) do { \
++ IOErrWhck("revert failure: " fmt " (%d, %d)\n", \
++ ##args, err, rerr); \
++ err = -EIO; \
++ } while(0)
++
++ out_diropq:
++ if (need_diropq) {
++ struct inode *h_inode;
++
++ h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
++ // i_lock simplly since inotify is not set to h_inode.
++ hi_lock_parent(h_inode);
++ //hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
++ rerr = remove_diropq(src_dentry, a->btgt, a->dlgt);
++ //rerr = -1;
++ //hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
++ i_unlock(h_inode);
++ if (rerr)
++ RevertFailure("remove diropq %.*s",
++ DLNPair(src_dentry));
++ }
++ out_rename:
++ if (!bycpup) {
++ struct dentry *d;
++ struct qstr *name = &src_dentry->d_name;
++ d = lkup_one(name->name, a->hidden_parent[SRC], name->len,
++ &lkup);
++ //d = ERR_PTR(-1);
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d)) {
++ RevertFailure("lkup_one %.*s", DLNPair(src_dentry));
++ goto out_whtmp;
++ }
++ DEBUG_ON(d->d_inode);
++ rerr = vfsub_rename
++ (hidden_dir[DST], au_h_dptr_i(src_dentry, a->btgt),
++ hidden_dir[SRC], d, a->dlgt);
++ //rerr = -1;
++ d_drop(d);
++ dput(d);
++ //set_h_dptr(src_dentry, a->btgt, NULL);
++ if (rerr)
++ RevertFailure("rename %.*s", DLNPair(src_dentry));
++ } else {
++ rerr = vfsub_unlink(hidden_dir[DST], a->hidden_dentry[DST],
++ a->dlgt);
++ //rerr = -1;
++ set_h_dptr(src_dentry, a->btgt, NULL);
++ set_dbstart(src_dentry, a->bstart[SRC]);
++ if (rerr)
++ RevertFailure("unlink %.*s",
++ DLNPair(a->hidden_dentry[DST]));
++ }
++ out_whtmp:
++ if (tharg) {
++ struct dentry *d;
++ struct qstr *name = &dentry->d_name;
++ LKTRLabel(here);
++ d = lkup_one(name->name, a->hidden_parent[DST], name->len,
++ &lkup);
++ //d = ERR_PTR(-1);
++ rerr = PTR_ERR(d);
++ if (IS_ERR(d)) {
++ RevertFailure("lookup %.*s", LNPair(name));
++ goto out_whdst;
++ }
++ if (d->d_inode) {
++ d_drop(d);
++ dput(d);
++ goto out_whdst;
++ }
++ DEBUG_ON(d->d_inode);
++ rerr = vfsub_rename(hidden_dir[DST], hidden_dst,
++ hidden_dir[DST], d, a->dlgt);
++ //rerr = -1;
++ d_drop(d);
++ dput(d);
++ if (rerr) {
++ RevertFailure("rename %.*s", DLNPair(hidden_dst));
++ goto out_whdst;
++ }
++ set_h_dptr(dentry, a->btgt, NULL);
++ set_h_dptr(dentry, a->btgt, dget(hidden_dst));
++ }
++ out_whdst:
++ dput(wh_dentry[DST]);
++ wh_dentry[DST] = NULL;
++ out_whsrc:
++ if (wh_dentry[SRC]) {
++ LKTRLabel(here);
++ rerr = au_unlink_wh_dentry(hidden_dir[SRC], wh_dentry[SRC],
++ src_dentry, a->dlgt);
++ //rerr = -1;
++ if (rerr)
++ RevertFailure("unlink %.*s", DLNPair(wh_dentry[SRC]));
++ }
++#undef RevertFailure
++ d_drop(src_dentry);
++ bend = dbend(src_dentry);
++ for (bindex = dbstart(src_dentry); bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(src_dentry, bindex);
++ if (hd)
++ d_drop(hd);
++ }
++ d_drop(dentry);
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(dentry, bindex);
++ if (hd)
++ d_drop(hd);
++ }
++ au_update_dbstart(dentry);
++ if (tharg)
++ d_drop(hidden_dst);
++ out_success:
++ dput(wh_dentry[SRC]);
++ dput(wh_dentry[DST]);
++ out_tharg:
++ if (tharg) {
++ dput(hidden_dst);
++ kfree(tharg);
++ }
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * test if @dentry dir can be rename destination or not.
++ * success means, it is a logically empty dir.
++ */
++static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
++ struct aufs_nhash *whlist)
++{
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ return test_empty(dentry, whlist);
++}
++
++/*
++ * test if @dentry dir can be rename source or not.
++ * if it can, return 0 and @children is filled.
++ * success means,
++ * - or, it is a logically empty dir.
++ * - or, it exists on writable branch and has no children including whiteouts
++ * on the lower branch.
++ */
++static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ int err;
++ aufs_bindex_t bstart;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++
++ bstart = dbstart(dentry);
++ if (bstart != btgt) {
++ struct aufs_nhash *whlist;
++
++ whlist = nhash_new(GFP_KERNEL);
++ err = PTR_ERR(whlist);
++ if (IS_ERR(whlist))
++ goto out;
++ err = test_empty(dentry, whlist);
++ nhash_del(whlist);
++ goto out;
++ }
++
++ if (bstart == dbtaildir(dentry))
++ return 0; /* success */
++
++ err = au_test_empty_lower(dentry);
++
++ out:
++ if (/* unlikely */(err == -ENOTEMPTY))
++ err = -EXDEV;
++ TraceErr(err);
++ return err;
++}
++
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry)
++{
++ int err, do_dt_dstdir;
++ aufs_bindex_t bend, bindex;
++ struct inode *inode, *dirs[2];
++ enum {PARENT, CHILD};
++ /* reduce stack space */
++ struct {
++ struct rename_args a;
++ struct dtime dt[2][2];
++ } *p;
++
++ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
++ src_dir->i_ino, DLNPair(src_dentry),
++ dir->i_ino, DLNPair(dentry));
++ IMustLock(src_dir);
++ IMustLock(dir);
++ /* braces are added to stop a warning */
++ if (dentry->d_inode) {
++ IMustLock(dentry->d_inode);
++ }
++
++ err = -ENOMEM;
++ BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
++ p = kmalloc(sizeof(*p), GFP_KERNEL);
++ if (unlikely(!p))
++ goto out;
++
++ err = -ENOTDIR;
++ p->a.sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ p->a.isdir = !!S_ISDIR(inode->i_mode);
++ if (unlikely(p->a.isdir && dentry->d_inode
++ && !S_ISDIR(dentry->d_inode->i_mode)))
++ goto out_free;
++
++ aufs_read_and_write_lock2(dentry, src_dentry, p->a.isdir);
++ p->a.dlgt = !!need_dlgt(p->a.sb);
++ p->a.parent[SRC] = p->a.parent[DST] = dentry->d_parent;
++ p->a.issamedir = (src_dir == dir);
++ if (p->a.issamedir)
++ di_write_lock_parent(p->a.parent[DST]);
++ else {
++ p->a.parent[SRC] = src_dentry->d_parent;
++ di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
++ /*isdir*/1);
++ }
++
++ /* which branch we process */
++ p->a.bstart[DST] = dbstart(dentry);
++ p->a.btgt = err = wr_dir(dentry, 1, src_dentry, /*force_btgt*/-1,
++ /*do_lock_srcdir*/0);
++ if (unlikely(err < 0))
++ goto out_unlock;
++
++ /* are they available to be renamed */
++ err = 0;
++ nhash_init(&p->a.whlist);
++ if (p->a.isdir && dentry->d_inode) {
++ set_dbstart(dentry, p->a.bstart[DST]);
++ err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
++ set_dbstart(dentry, p->a.btgt);
++ }
++ p->a.hidden_dentry[DST] = au_h_dptr(dentry);
++ if (unlikely(err))
++ goto out_unlock;
++ //todo: minor optimize, their sb may be same while their bindex differs.
++ p->a.bstart[SRC] = dbstart(src_dentry);
++ p->a.hidden_dentry[SRC] = au_h_dptr(src_dentry);
++ if (p->a.isdir) {
++ err = may_rename_srcdir(src_dentry, p->a.btgt);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ /* prepare the writable parent dir on the same branch */
++ err = wr_dir_need_wh(src_dentry, p->a.isdir, &p->a.btgt,
++ p->a.issamedir ? NULL : p->a.parent[DST]);
++ if (unlikely(err < 0))
++ goto out_children;
++ p->a.whsrc = !!err;
++ p->a.whdst = (p->a.bstart[DST] == p->a.btgt);
++ if (!p->a.whdst) {
++ err = cpup_dirs(dentry, p->a.btgt,
++ p->a.issamedir ? NULL : p->a.parent[SRC]);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ p->a.hidden_parent[SRC] = au_h_dptr_i(p->a.parent[SRC], p->a.btgt);
++ p->a.hidden_parent[DST] = au_h_dptr_i(p->a.parent[DST], p->a.btgt);
++ dirs[0] = src_dir;
++ dirs[1] = dir;
++ hdir_lock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++
++ /* store timestamps to be revertible */
++ dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
++ p->a.hidden_parent[SRC]);
++ if (!p->a.issamedir)
++ dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
++ p->a.hidden_parent[DST]);
++ do_dt_dstdir = 0;
++ if (p->a.isdir) {
++ dtime_store(p->dt[CHILD] + SRC, src_dentry,
++ p->a.hidden_dentry[SRC]);
++ if (p->a.hidden_dentry[DST]->d_inode) {
++ do_dt_dstdir = 1;
++ dtime_store(p->dt[CHILD] + DST, dentry,
++ p->a.hidden_dentry[DST]);
++ }
++ }
++
++ err = do_rename(src_dir, src_dentry, dir, dentry, &p->a);
++ if (unlikely(err))
++ goto out_dt;
++ hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++
++ /* update dir attributes */
++ dir->i_version++;
++ if (p->a.isdir)
++ au_cpup_attr_nlink(dir);
++ if (ibstart(dir) == p->a.btgt)
++ au_cpup_attr_timesizes(dir);
++
++ if (!p->a.issamedir) {
++ src_dir->i_version++;
++ if (p->a.isdir)
++ au_cpup_attr_nlink(src_dir);
++ if (ibstart(src_dir) == p->a.btgt)
++ au_cpup_attr_timesizes(src_dir);
++ }
++
++ // is this updating defined in POSIX?
++ if (unlikely(p->a.isdir)) {
++ //i_lock(inode);
++ au_cpup_attr_timesizes(inode);
++ //i_unlock(inode);
++ }
++
++#if 0
++ d_drop(src_dentry);
++#else
++ /* dput/iput all lower dentries */
++ set_dbwh(src_dentry, -1);
++ bend = dbend(src_dentry);
++ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
++ struct dentry *hd;
++ hd = au_h_dptr_i(src_dentry, bindex);
++ if (hd)
++ set_h_dptr(src_dentry, bindex, NULL);
++ }
++ set_dbend(src_dentry, p->a.btgt);
++
++ bend = ibend(inode);
++ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
++ struct inode *hi;
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi)
++ set_h_iptr(inode, bindex, NULL, 0);
++ }
++ set_ibend(inode, p->a.btgt);
++#endif
++
++#if 0
++ //au_debug_on();
++ //DbgDentry(dentry);
++ //DbgInode(dentry->d_inode);
++ //au_debug_off();
++ inode = dentry->d_inode;
++ if (inode) {
++ aufs_bindex_t bindex, bend;
++ struct dentry *hd;
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ hd = au_h_dptr_i(dentry, bindex);
++ if (hd && hd->d_inode)
++ xino_write0(p->a.sb, bindex, hd->d_inode->i_ino);
++ /* ignore this error */
++ }
++ }
++#endif
++
++ goto out_children; /* success */
++
++ out_dt:
++ dtime_revert(p->dt[PARENT] + SRC,
++ p->a.hidden_parent[SRC]->d_parent
++ == p->a.hidden_parent[DST]);
++ if (!p->a.issamedir)
++ dtime_revert(p->dt[PARENT] + DST,
++ p->a.hidden_parent[DST]->d_parent
++ == p->a.hidden_parent[SRC]);
++ if (p->a.isdir && err != -EIO) {
++ struct dentry *hd;
++
++ hd = p->dt[CHILD][SRC].dt_h_dentry;
++ hi_lock_child(hd->d_inode);
++ dtime_revert(p->dt[CHILD] + SRC, 1);
++ i_unlock(hd->d_inode);
++ if (do_dt_dstdir) {
++ hd = p->dt[CHILD][DST].dt_h_dentry;
++ hi_lock_child(hd->d_inode);
++ dtime_revert(p->dt[CHILD] + DST, 1);
++ i_unlock(hd->d_inode);
++ }
++ }
++ hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
++ out_children:
++ nhash_fin(&p->a.whlist);
++ out_unlock:
++ //if (unlikely(err /* && p->a.isdir */)) {
++ if (unlikely(err && p->a.isdir)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ if (p->a.issamedir)
++ di_write_unlock(p->a.parent[DST]);
++ else
++ di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ out_free:
++ kfree(p);
++ out:
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/iinfo.c linux-2.6.22.1/fs/aufs/iinfo.c
+--- linux-2.6.22.1.oorig/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/iinfo.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,286 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: iinfo.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/mm.h>
++#include "aufs.h"
++
++struct aufs_iinfo *itoii(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++
++ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
++ /* bad_inode case */
++ if (unlikely(!iinfo->ii_hinode))
++ return NULL;
++ DEBUG_ON(!iinfo->ii_hinode
++ /* || stosi(inode->i_sb)->si_bend < iinfo->ii_bend */
++ || iinfo->ii_bend < iinfo->ii_bstart);
++ return iinfo;
++}
++
++aufs_bindex_t ibstart(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ return itoii(inode)->ii_bstart;
++}
++
++aufs_bindex_t ibend(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ return itoii(inode)->ii_bend;
++}
++
++struct aufs_vdir *ivdir(struct inode *inode)
++{
++ IiMustAnyLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++ return itoii(inode)->ii_vdir;
++}
++
++struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct inode *hidden_inode;
++
++ IiMustAnyLock(inode);
++ DEBUG_ON(bindex < 0 || ibend(inode) < bindex);
++ hidden_inode = itoii(inode)->ii_hinode[0 + bindex].hi_inode;
++ DEBUG_ON(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
++ return hidden_inode;
++}
++
++struct inode *au_h_iptr(struct inode *inode)
++{
++ return au_h_iptr_i(inode, ibstart(inode));
++}
++
++aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex)
++{
++ IiMustAnyLock(inode);
++ DEBUG_ON(bindex < 0
++ || ibend(inode) < bindex
++ || !itoii(inode)->ii_hinode[0 + bindex].hi_inode);
++ return itoii(inode)->ii_hinode[0 + bindex].hi_id;
++}
++
++// hard/soft set
++void set_ibstart(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct aufs_iinfo *iinfo = itoii(inode);
++ struct inode *h_inode;
++
++ IiMustWriteLock(inode);
++ DEBUG_ON(sbend(inode->i_sb) < bindex);
++ iinfo->ii_bstart = bindex;
++ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
++ if (h_inode)
++ au_cpup_igen(inode, h_inode);
++}
++
++void set_ibend(struct inode *inode, aufs_bindex_t bindex)
++{
++ IiMustWriteLock(inode);
++ DEBUG_ON(sbend(inode->i_sb) < bindex
++ || bindex < ibstart(inode));
++ itoii(inode)->ii_bend = bindex;
++}
++
++void set_ivdir(struct inode *inode, struct aufs_vdir *vdir)
++{
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode)
++ || (itoii(inode)->ii_vdir && vdir));
++ itoii(inode)->ii_vdir = vdir;
++}
++
++void aufs_hiput(struct aufs_hinode *hinode)
++{
++ if (unlikely(hinode->hi_notify))
++ do_free_hinotify(hinode);
++ if (hinode->hi_inode)
++ iput(hinode->hi_inode);
++}
++
++unsigned int au_hi_flags(struct inode *inode, int isdir)
++{
++ unsigned int flags;
++ struct super_block *sb = inode->i_sb;
++
++ flags = 0;
++ if (au_flag_test(sb, AuFlag_XINO))
++ flags = AUFS_HI_XINO;
++ if (unlikely(isdir && au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ flags |= AUFS_HI_NOTIFY;
++ return flags;
++}
++
++void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags)
++{
++ struct aufs_hinode *hinode;
++ struct inode *hi;
++ struct aufs_iinfo *iinfo = itoii(inode);
++
++ LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
++ inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
++ IiMustWriteLock(inode);
++ hinode = iinfo->ii_hinode + bindex;
++ hi = hinode->hi_inode;
++ DEBUG_ON(bindex < ibstart(inode) || ibend(inode) < bindex
++ || (h_inode && atomic_read(&h_inode->i_count) <= 0)
++ || (h_inode && hi));
++
++ if (hi)
++ aufs_hiput(hinode);
++ hinode->hi_inode = h_inode;
++ if (h_inode) {
++ int err;
++ struct super_block *sb = inode->i_sb;
++
++ if (bindex == iinfo->ii_bstart)
++ au_cpup_igen(inode, h_inode);
++ hinode->hi_id = sbr_id(sb, bindex);
++ if (flags & AUFS_HI_XINO) {
++ struct xino xino = {
++ .ino = inode->i_ino,
++ //.h_gen = h_inode->i_generation
++ };
++ //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ err = xino_write(sb, bindex, h_inode->i_ino, &xino);
++ if (unlikely(err)) {
++ IOErr1("failed xino_write() %d, force noxino\n",
++ err);
++ au_flag_clr(sb, AuFlag_XINO);
++ }
++ }
++ if (flags & AUFS_HI_NOTIFY) {
++ err = alloc_hinotify(hinode, inode, h_inode);
++ if (unlikely(err))
++ IOErr1("alloc_hinotify() %d\n", err);
++ else {
++ /* braces are added to stop a warning */
++ DEBUG_ON(!hinode->hi_notify);
++ }
++ }
++ }
++}
++
++void au_update_iigen(struct inode *inode)
++{
++ //IiMustWriteLock(inode);
++ DEBUG_ON(!inode->i_sb);
++ atomic_set(&itoii(inode)->ii_generation, au_sigen(inode->i_sb));
++}
++
++/* it may be called at remount time, too */
++void au_update_brange(struct inode *inode, int do_put_zero)
++{
++ struct aufs_iinfo *iinfo;
++
++ LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
++ IiMustWriteLock(inode);
++
++ iinfo = itoii(inode);
++ if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++) {
++ struct inode *h_i;
++ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
++ if (h_i && !h_i->i_nlink)
++ set_h_iptr(inode, bindex, NULL, 0);
++ }
++ }
++
++ iinfo->ii_bstart = -1;
++ while (++iinfo->ii_bstart <= iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
++ break;
++ if (iinfo->ii_bstart > iinfo->ii_bend) {
++ iinfo->ii_bend = iinfo->ii_bstart = -1;
++ return;
++ }
++
++ iinfo->ii_bend++;
++ while (0 <= --iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
++ break;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_iinfo_init(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++ struct super_block *sb;
++ int nbr, i;
++
++ sb = inode->i_sb;
++ DEBUG_ON(!sb);
++ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
++ DEBUG_ON(iinfo->ii_hinode);
++ nbr = sbend(sb) + 1;
++ if (unlikely(!nbr))
++ nbr++;
++ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
++ //iinfo->ii_hinode = NULL;
++ if (iinfo->ii_hinode) {
++ for (i = 0; i < nbr; i++)
++ iinfo->ii_hinode[i].hi_id = -1;
++ atomic_set(&iinfo->ii_generation, au_sigen(sb));
++ rw_init_nolock(&iinfo->ii_rwsem);
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ iinfo->ii_vdir = NULL;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++void au_iinfo_fin(struct inode *inode)
++{
++ struct aufs_iinfo *iinfo;
++
++ iinfo = itoii(inode);
++ /* bad_inode case */
++ if (unlikely(!iinfo))
++ return;
++
++ if (unlikely(iinfo->ii_vdir))
++ free_vdir(iinfo->ii_vdir);
++
++ if (iinfo->ii_bstart >= 0) {
++ aufs_bindex_t bend;
++ struct aufs_hinode *hi;
++ hi = iinfo->ii_hinode + iinfo->ii_bstart;
++ bend = iinfo->ii_bend;
++ while (iinfo->ii_bstart++ <= bend) {
++ if (hi->hi_inode)
++ aufs_hiput(hi);
++ hi++;
++ }
++ //iinfo->ii_bstart = iinfo->ii_bend = -1;
++ }
++
++ kfree(iinfo->ii_hinode);
++ //iinfo->ii_hinode = NULL;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/inode.c linux-2.6.22.1/fs/aufs/inode.c
+--- linux-2.6.22.1.oorig/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/inode.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,339 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: inode.c,v 1.22 2007/05/07 03:44:35 sfjro Exp $ */
++
++#include "aufs.h"
++
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
++{
++ int err, new_sz, update, isdir;
++ struct inode *first;
++ struct aufs_hinode *p, *q, tmp;
++ struct super_block *sb;
++ struct aufs_iinfo *iinfo;
++ aufs_bindex_t bindex, bend, new_bindex;
++ unsigned int flags;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ IiMustWriteLock(inode);
++
++ err = -ENOMEM;
++ sb = dentry->d_sb;
++ bend = sbend(sb);
++ new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
++ iinfo = itoii(inode);
++ p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
++ new_sz, GFP_KERNEL);
++ //p = NULL;
++ if (unlikely(!p))
++ goto out;
++
++ iinfo->ii_hinode = p;
++ err = 0;
++ update = 0;
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++, p++) {
++ if (unlikely(!p->hi_inode))
++ continue;
++
++ new_bindex = find_brindex(sb, p->hi_id);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) {
++ update++;
++ aufs_hiput(p);
++ p->hi_inode = NULL;
++ continue;
++ }
++
++ if (new_bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = new_bindex;
++ if (iinfo->ii_bend < new_bindex)
++ iinfo->ii_bend = new_bindex;
++ /* swap two hidden inode, and loop again */
++ q = iinfo->ii_hinode + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hi_inode) {
++ bindex--;
++ p--;
++ }
++ }
++
++ isdir = S_ISDIR(inode->i_mode);
++ flags = au_hi_flags(inode, isdir);
++ bend = dbend(dentry);
++ for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
++ struct inode *hi;
++ struct dentry *hd;
++
++ hd = au_h_dptr_i(dentry, bindex);
++ if (!hd || !hd->d_inode)
++ continue;
++
++ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
++ hi = au_h_iptr_i(inode, bindex);
++ if (hi) {
++ if (hi == hd->d_inode)
++ continue;
++ //Dbg("here\n");
++ err = -ESTALE;
++ break;
++ }
++ }
++ if (bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = bindex;
++ if (iinfo->ii_bend < bindex)
++ iinfo->ii_bend = bindex;
++ set_h_iptr(inode, bindex, igrab(hd->d_inode), flags);
++ update++;
++ }
++
++ bend = iinfo->ii_bend;
++ p = iinfo->ii_hinode;
++ for (bindex = 0; bindex <= bend; bindex++, p++)
++ if (p->hi_inode) {
++ iinfo->ii_bstart = bindex;
++ break;
++ }
++ p = iinfo->ii_hinode + bend;
++ for (bindex = bend; bindex > iinfo->ii_bstart; bindex--, p--)
++ if (p->hi_inode) {
++ iinfo->ii_bend = bindex;
++ break;
++ }
++ DEBUG_ON(iinfo->ii_bstart > bend || iinfo->ii_bend < 0);
++
++ if (unlikely(err))
++ goto out;
++
++ if (1 || first != au_h_iptr(inode))
++ au_cpup_attr_all(inode);
++ if (update && isdir)
++ inode->i_version++;
++ au_update_iigen(inode);
++
++ out:
++ //au_debug_on();
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++static int set_inode(struct inode *inode, struct dentry *dentry)
++{
++ int err, isdir;
++ struct dentry *hidden_dentry;
++ struct inode *hidden_inode;
++ umode_t mode;
++ aufs_bindex_t bindex, bstart, btail;
++ struct aufs_iinfo *iinfo;
++ unsigned int flags;
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++ DEBUG_ON(!(inode->i_state & I_NEW));
++ IiMustWriteLock(inode);
++ hidden_dentry = au_h_dptr(dentry);
++ DEBUG_ON(!hidden_dentry);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_inode);
++
++ err = 0;
++ isdir = 0;
++ bstart = dbstart(dentry);
++ mode = hidden_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ btail = dbtail(dentry);
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ btail = dbtaildir(dentry);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ break;
++ case S_IFLNK:
++ btail = dbtail(dentry);
++ inode->i_op = &aufs_symlink_iop;
++ break;
++ case S_IFBLK:
++ case S_IFCHR:
++ case S_IFIFO:
++ case S_IFSOCK:
++ btail = dbtail(dentry);
++ init_special_inode(inode, mode, hidden_inode->i_rdev);
++ break;
++ default:
++ IOErr("Unknown file type 0%o\n", mode);
++ err = -EIO;
++ goto out;
++ }
++
++ flags = au_hi_flags(inode, isdir);
++ iinfo = itoii(inode);
++ iinfo->ii_bstart = bstart;
++ iinfo->ii_bend = btail;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!hidden_dentry)
++ continue;
++ DEBUG_ON(!hidden_dentry->d_inode);
++ set_h_iptr(inode, bindex, igrab(hidden_dentry->d_inode), flags);
++ }
++ au_cpup_attr_all(inode);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++//todo: return with unlocked?
++static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
++{
++ int err;
++ struct inode *h_inode, *h_dinode;
++ aufs_bindex_t bindex, bend;
++ //const int udba = !au_flag_test(inode->i_sb, AuFlag_UDBA_NONE);
++
++ LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
++
++ *matched = 0;
++
++ /*
++ * before this function, if aufs got any iinfo lock, it must be only
++ * one, the parent dir.
++ * it can happen by UDBA and the obsoleted inode number.
++ */
++ err = -EIO;
++ if (unlikely(inode->i_ino == parent_ino(dentry)))
++ goto out;
++
++ h_dinode = au_h_dptr(dentry)->d_inode;
++ hi_lock_child(inode); // bad name, this is not a hidden inode.
++ ii_write_lock_new(inode);
++ bend = ibend(inode);
++ for (bindex = ibstart(inode); bindex <= bend; bindex++) {
++ h_inode = au_h_iptr_i(inode, bindex);
++ if (h_inode && h_inode == h_dinode) {
++ //&& (ibs != bstart || !au_test_higen(inode, h_inode)));
++ *matched = 1;
++ err = 0;
++ if (unlikely(au_iigen(inode) != au_digen(dentry)))
++ err = au_refresh_hinode(inode, dentry);
++ break;
++ }
++ }
++ i_unlock(inode);
++ if (unlikely(err))
++ ii_write_unlock(inode);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++//todo: return with unlocked?
++struct inode *au_new_inode(struct dentry *dentry)
++{
++ struct inode *inode, *h_inode;
++ struct dentry *h_dentry;
++ ino_t h_ino;
++ struct super_block *sb;
++ int err, match;
++ aufs_bindex_t bstart;
++ struct xino xino;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ sb = dentry->d_sb;
++ h_dentry = au_h_dptr(dentry);
++ DEBUG_ON(!h_dentry);
++ h_inode = h_dentry->d_inode;
++ DEBUG_ON(!h_inode);
++
++ bstart = dbstart(dentry);
++ h_ino = h_inode->i_ino;
++ err = xino_read(sb, bstart, h_ino, &xino);
++ //err = -1;
++ inode = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++ new_ino:
++ if (!xino.ino) {
++ xino.ino = xino_new_ino(sb);
++ if (!xino.ino) {
++ inode = ERR_PTR(-EIO);
++ goto out;
++ }
++ }
++
++ LKTRTrace("i%lu\n", xino.ino);
++ err = -ENOMEM;
++ inode = iget_locked(sb, xino.ino);
++ if (unlikely(!inode))
++ goto out;
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++ err = -ENOMEM;
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
++ if (inode->i_state & I_NEW) {
++ sb->s_op->read_inode(inode);
++ if (!is_bad_inode(inode)) {
++ ii_write_lock_new(inode);
++ err = set_inode(inode, dentry);
++ //err = -1;
++ }
++ unlock_new_inode(inode);
++ if (!err)
++ goto out; /* success */
++ ii_write_unlock(inode);
++ goto out_iput;
++ } else {
++ err = reval_inode(inode, dentry, &match);
++ if (!err)
++ goto out; /* success */
++ else if (match)
++ goto out_iput;
++ }
++
++ Warn1("broken ino, b%d, %.*s/%.*s, hi%lu, i%lu. Try udba=inotify.\n",
++ bstart, DLNPair(dentry->d_parent), DLNPair(dentry), h_ino,
++ xino.ino);
++ xino.ino = 0;
++ err = xino_write0(sb, bstart, h_ino);
++ if (!err) {
++ iput(inode);
++ goto new_ino;
++ }
++
++ out_iput:
++ iput(inode);
++ inode = ERR_PTR(err);
++ out:
++ TraceErrPtr(inode);
++ return inode;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/inode.h linux-2.6.22.1/fs/aufs/inode.h
+--- linux-2.6.22.1.oorig/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/inode.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,377 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: inode.h,v 1.32 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_INODE_H__
++#define __AUFS_INODE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/inotify.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "vfsub.h"
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#else
++struct inotify_watch {};
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_hinotify {
++ struct inotify_watch hin_watch;
++ struct inode *hin_aufs_inode; /* no get/put */
++};
++
++struct aufs_hinode {
++ struct inode *hi_inode;
++ aufs_bindex_t hi_id;
++ struct aufs_hinotify *hi_notify;
++};
++
++struct aufs_vdir;
++struct aufs_iinfo {
++ atomic_t ii_generation;
++ struct super_block *ii_hsb1; /* no get/put */
++
++ struct aufs_rwsem ii_rwsem;
++ aufs_bindex_t ii_bstart, ii_bend;
++ struct aufs_hinode *ii_hinode;
++ struct aufs_vdir *ii_vdir;
++};
++
++struct aufs_icntnr {
++ struct aufs_iinfo iinfo;
++ struct inode vfs_inode;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* inode.c */
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
++struct inode *au_new_inode(struct dentry *dentry);
++
++/* i_op.c */
++extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
++int wr_dir(struct dentry *dentry, int negative, struct dentry *src_dentry,
++ aufs_bindex_t force_btgt, int do_lock_srcdir);
++
++/* i_op_del.c */
++int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
++ struct dentry *locked);
++
++/* iinfo.c */
++struct aufs_iinfo *itoii(struct inode *inode);
++aufs_bindex_t ibstart(struct inode *inode);
++aufs_bindex_t ibend(struct inode *inode);
++struct aufs_vdir *ivdir(struct inode *inode);
++struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex);
++struct inode *au_h_iptr(struct inode *inode);
++aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex);
++
++void set_ibstart(struct inode *inode, aufs_bindex_t bindex);
++void set_ibend(struct inode *inode, aufs_bindex_t bindex);
++void set_ivdir(struct inode *inode, struct aufs_vdir *vdir);
++void aufs_hiput(struct aufs_hinode *hinode);
++#define AUFS_HI_XINO 1
++#define AUFS_HI_NOTIFY 2
++unsigned int au_hi_flags(struct inode *inode, int isdir);
++void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags);
++void au_update_iigen(struct inode *inode);
++void au_update_brange(struct inode *inode, int do_put_zero);
++
++int au_iinfo_init(struct inode *inode);
++void au_iinfo_fin(struct inode *inode);
++
++/* plink.c */
++#ifdef CONFIG_AUFS_DEBUG
++void au_list_plink(struct super_block *sb);
++#else
++static inline void au_list_plink(struct super_block *sb)
++{
++ /* nothing */
++}
++#endif
++int au_is_plinked(struct super_block *sb, struct inode *inode);
++struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode);
++void append_plink(struct super_block *sb, struct inode *inode,
++ struct dentry *h_dentry, aufs_bindex_t bindex);
++void au_put_plink(struct super_block *sb);
++void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id);
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for hidden inode */
++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
++// todo: reduce it by dcsub.
++enum {
++ AuLsc_Begin = I_MUTEX_QUOTA,
++ AuLsc_HI_GPARENT, /* setattr with inotify */
++ AuLsc_HI_PARENT, /* hidden inode, parent first */
++ AuLsc_HI_CHILD,
++ AuLsc_HI_PARENT2, /* copyup dirs */
++ AuLsc_HI_CHILD2,
++ AuLsc_End
++};
++
++/* simple abstraction */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++static inline void i_lock(struct inode *i)
++{
++ down(&i->i_sem);
++}
++
++static inline void i_unlock(struct inode *i)
++{
++ up(&i->i_sem);
++}
++
++static inline int i_trylock(struct inode *i)
++{
++ return down_trylock(&i->i_sem);
++}
++
++static inline void hi_lock(struct inode *i, unsigned int lsc)
++{
++ i_lock(i);
++}
++
++#define IMustLock(i) DEBUG_ON(!down_trylock(&(i)->i_sem))
++#else
++static inline void i_lock(struct inode *i)
++{
++ mutex_lock(&i->i_mutex);
++}
++
++static inline void i_unlock(struct inode *i)
++{
++ mutex_unlock(&i->i_mutex);
++}
++
++static inline int i_trylock(struct inode *i)
++{
++ return mutex_trylock(&i->i_mutex);
++}
++
++static inline void hi_lock(struct inode *i, unsigned int lsc)
++{
++ mutex_lock_nested(&i->i_mutex, lsc);
++}
++
++#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
++#endif
++
++/*
++ * hi_lock_gparent, hi_lock_parent, hi_lock_parent2, hi_lock_child,
++ * hi_lock_child2, hi_lock_whplink
++ */
++#define LockFunc(name, lsc) \
++static inline void hi_lock_##name(struct inode *h_i) \
++{hi_lock(h_i, AuLsc_HI_##lsc);}
++
++LockFunc(gparent, GPARENT);
++LockFunc(parent, PARENT);
++LockFunc(parent2, PARENT2);
++LockFunc(child, CHILD);
++LockFunc(child2, CHILD2);
++LockFunc(whplink, CHILD2); /* sharing lock-subclass */
++
++#undef LockFunc
++
++/* ---------------------------------------------------------------------- */
++
++/* tiny test for inode number */
++/* tmpfs generation is too rough */
++static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
++{
++ //IiMustAnyLock(inode);
++ return !(itoii(inode)->ii_hsb1 == h_inode->i_sb
++ && inode->i_generation == h_inode->i_generation);
++}
++
++static inline int au_iigen(struct inode *inode)
++{
++ return atomic_read(&itoii(inode)->ii_generation);
++}
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_iigen_dec(struct inode *inode)
++{
++ //Dbg("i%lu\n", inode->i_ino);
++ atomic_dec(&itoii(inode)->ii_generation);
++}
++
++/* hinotify.c */
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *h_inode);
++void do_free_hinotify(struct aufs_hinode *hinode);
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc);
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex);
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir);
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir);
++void au_reset_hinotify(struct inode *inode, unsigned int flags);
++int __init au_inotify_init(void);
++void au_inotify_fin(void);
++#else
++static inline
++int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
++ struct inode *h_inode)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline void do_free_hinotify(struct aufs_hinode *hinode)
++{
++ /* nothing */
++}
++
++static inline
++void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
++ unsigned int lsc)
++{
++ hi_lock(h_dir, lsc);
++}
++
++static inline
++void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
++{
++ i_unlock(h_dir);
++}
++
++static inline
++void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ vfsub_lock_rename(h_parents[0], h_parents[1]);
++}
++
++static inline
++void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
++ aufs_bindex_t bindex, int issamedir)
++{
++ vfsub_unlock_rename(h_parents[0], h_parents[1]);
++}
++
++static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ /* nothing */
++}
++
++#define au_inotify_init() 0
++#define au_inotify_fin() /* */
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++static inline void free_hinotify(struct inode *inode, aufs_bindex_t bindex)
++{
++ do_free_hinotify(itoii(inode)->ii_hinode + bindex);
++}
++
++/*
++ * hgdir_lock, hdir_lock, hdir2_lock
++ */
++#define LockFunc(name, lsc) \
++static inline \
++void name##_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex) \
++{do_hdir_lock(h_dir, dir, bindex, AuLsc_HI_##lsc);}
++
++LockFunc(hgdir, GPARENT);
++LockFunc(hdir, PARENT);
++LockFunc(hdir2, PARENT2);
++
++#undef LockFunc
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for iinfo */
++enum {
++ AuLsc_II_CHILD, /* child first */
++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_II_CHILD3, /* copyup dirs */
++ AuLsc_II_PARENT,
++ AuLsc_II_PARENT2,
++ AuLsc_II_PARENT3,
++ AuLsc_II_NEW /* new inode */
++};
++
++/*
++ * ii_read_lock_child, ii_write_lock_child,
++ * ii_read_lock_child2, ii_write_lock_child2,
++ * ii_read_lock_child3, ii_write_lock_child3,
++ * ii_read_lock_parent, ii_write_lock_parent,
++ * ii_read_lock_parent2, ii_write_lock_parent2,
++ * ii_read_lock_parent3, ii_write_lock_parent3,
++ * ii_read_lock_new, ii_write_lock_new
++ */
++#define ReadLockFunc(name, lsc) \
++static inline void ii_read_lock_##name(struct inode *i) \
++{rw_read_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
++
++#define WriteLockFunc(name, lsc) \
++static inline void ii_write_lock_##name(struct inode *i) \
++{rw_write_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
++
++#define RWLockFuncs(name, lsc) \
++ ReadLockFunc(name, lsc); \
++ WriteLockFunc(name, lsc)
++
++RWLockFuncs(child, CHILD);
++RWLockFuncs(child2, CHILD2);
++RWLockFuncs(child3, CHILD3);
++RWLockFuncs(parent, PARENT);
++RWLockFuncs(parent2, PARENT2);
++RWLockFuncs(parent3, PARENT3);
++RWLockFuncs(new, NEW);
++
++#undef ReadLockFunc
++#undef WriteLockFunc
++#undef RWLockFunc
++
++/*
++ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
++ */
++SimpleUnlockRwsemFuncs(ii, struct inode *i, itoii(i)->ii_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define IiMustReadLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustReadLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustWriteLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustWriteLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustAnyLock(i) do { \
++ SiMustAnyLock((i)->i_sb); \
++ RwMustAnyLock(&itoii(i)->ii_rwsem); \
++} while (0)
++
++#define IiMustNoWaiters(i) RwMustNoWaiters(&itoii(i)->ii_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_INODE_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/misc.c linux-2.6.22.1/fs/aufs/misc.c
+--- linux-2.6.22.1.oorig/fs/aufs/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/misc.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,228 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: misc.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
++
++//#include <linux/fs.h>
++//#include <linux/namei.h>
++//#include <linux/mm.h>
++//#include <asm/uaccess.h>
++#include "aufs.h"
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
++{
++ void *q;
++
++ LKTRTrace("p %p, nused %d, sz %d, ksize %d\n",
++ p, nused, new_sz, ksize(p));
++ DEBUG_ON(new_sz <= 0);
++ if (new_sz <= nused)
++ return p;
++ if (new_sz <= ksize(p)) {
++ memset(p + nused, 0, new_sz - nused);
++ return p;
++ }
++
++ q = kmalloc(new_sz, gfp);
++ //q = NULL;
++ if (unlikely(!q))
++ return NULL;
++ memcpy(q, p, nused);
++ memset(q + nused, 0, new_sz - nused);
++ //smp_mb();
++ kfree(p);
++ return q;
++}
++
++/* ---------------------------------------------------------------------- */
++
++// todo: make it inline
++struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
++ struct super_block *sb, aufs_bindex_t bindex)
++{
++ LKTRTrace("nd %p, b%d\n", nd, bindex);
++
++ if (!nd)
++ return NULL;
++
++ fake_nd->dentry = NULL;
++ fake_nd->mnt = NULL;
++
++#ifndef CONFIG_AUFS_FAKE_DM
++ DiMustAnyLock(nd->dentry);
++
++ if (bindex <= dbend(nd->dentry))
++ fake_nd->dentry = au_h_dptr_i(nd->dentry, bindex);
++ if (fake_nd->dentry) {
++ dget(fake_nd->dentry);
++ fake_nd->mnt = sbr_mnt(sb, bindex);
++ DEBUG_ON(!fake_nd->mnt);
++ mntget(fake_nd->mnt);
++ } else
++ fake_nd = ERR_PTR(-ENOENT);
++#endif
++
++ TraceErrPtr(fake_nd);
++ return fake_nd;
++}
++
++void fake_dm_release(struct nameidata *fake_nd)
++{
++#ifndef CONFIG_AUFS_FAKE_DM
++ if (fake_nd) {
++ mntput(fake_nd->mnt);
++ dput(fake_nd->dentry);
++ }
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len,
++ struct super_block *sb, int *sparse)
++{
++ int err, all_zero, dlgt;
++ unsigned long blksize;
++ char *buf;
++ /* reduce stack space */
++ struct iattr *ia;
++
++ LKTRTrace("%.*s, %.*s\n",
++ DLNPair(dst->f_dentry), DLNPair(src->f_dentry));
++ DEBUG_ON(!(dst->f_mode & FMODE_WRITE));
++ IMustLock(dst->f_dentry->d_parent->d_inode);
++
++ err = -ENOMEM;
++ blksize = dst->f_dentry->d_sb->s_blocksize;
++ if (!blksize || PAGE_SIZE < blksize)
++ blksize = PAGE_SIZE;
++ LKTRTrace("blksize %lu\n", blksize);
++ buf = kmalloc(blksize, GFP_KERNEL);
++ //buf = NULL;
++ if (unlikely(!buf))
++ goto out;
++ ia = kmalloc(sizeof(*ia), GFP_KERNEL);
++ if (unlikely(!ia))
++ goto out_buf;
++
++ dlgt = need_dlgt(sb);
++ err = all_zero = 0;
++ dst->f_pos = src->f_pos = 0;
++ while (len) {
++ size_t sz, rbytes, wbytes, i;
++ char *p;
++
++ LKTRTrace("len %lld\n", len);
++ sz = blksize;
++ if (len < blksize)
++ sz = len;
++
++ /* support LSM and notify */
++ rbytes = 0;
++ while (!rbytes || err == -EAGAIN || err == -EINTR)
++ err = rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
++ dlgt);
++ if (unlikely(err < 0))
++ break;
++
++ all_zero = 0;
++ if (len >= rbytes && rbytes == blksize) {
++ all_zero = 1;
++ p = buf;
++ for (i = 0; all_zero && i < rbytes; i++)
++ all_zero = !*p++;
++ }
++ if (!all_zero) {
++ wbytes = rbytes;
++ p = buf;
++ while (wbytes) {
++ size_t b;
++ /* support LSM and notify */
++ err = b = vfsub_write_k(dst, p, wbytes,
++ &dst->f_pos, dlgt);
++ if (unlikely(err == -EAGAIN || err == -EINTR))
++ continue;
++ if (unlikely(err < 0))
++ break;
++ wbytes -= b;
++ p += b;
++ }
++ } else {
++ loff_t res;
++ LKTRLabel(hole);
++ *sparse = 1;
++ err = res = vfsub_llseek(dst, rbytes, SEEK_CUR);
++ if (unlikely(res < 0))
++ break;
++ }
++ len -= rbytes;
++ err = 0;
++ }
++
++ /* the last block may be a hole */
++ if (unlikely(!err && all_zero)) {
++ struct dentry *h_d = dst->f_dentry;
++ struct inode *h_i = h_d->d_inode;
++
++ LKTRLabel(last hole);
++ do {
++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, dlgt);
++ } while (err == -EAGAIN || err == -EINTR);
++ if (err == 1) {
++ ia->ia_size = dst->f_pos;
++ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
++ ia->ia_file = dst;
++ hi_lock_child2(h_i);
++ err = vfsub_notify_change(h_d, ia, dlgt);
++ i_unlock(h_i);
++ }
++ }
++
++ kfree(ia);
++ out_buf:
++ kfree(buf);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode)
++{
++ int err;
++
++ err = br_rdonly(stobr(sb, bindex));
++ if (!err && inode) {
++ struct inode *hi = au_h_iptr_i(inode, bindex);
++ if (hi)
++ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
++ }
++ return err;
++}
++
++int au_test_perm(struct inode *hidden_inode, int mask, int dlgt)
++{
++ if (!current->fsuid)
++ return 0;
++ if (unlikely(au_is_nfs(hidden_inode->i_sb)
++ && (mask & MAY_WRITE)
++ && S_ISDIR(hidden_inode->i_mode)))
++ mask |= MAY_READ; /* force permission check */
++ return vfsub_permission(hidden_inode, mask, NULL, dlgt);
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/misc.h linux-2.6.22.1/fs/aufs/misc.h
+--- linux-2.6.22.1.oorig/fs/aufs/misc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/misc.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,187 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: misc.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_MISC_H__
++#define __AUFS_MISC_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/sched.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#define I_MUTEX_QUOTA 0
++#define lockdep_off() /* */
++#define lockdep_on() /* */
++#define mutex_lock_nested(mtx, lsc) mutex_lock(mtx)
++#define down_write_nested(rw, lsc) down_write(rw)
++#define down_read_nested(rw, lsc) down_read(rw)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_rwsem {
++ struct rw_semaphore rwsem;
++#ifdef CONFIG_AUFS_DEBUG
++ atomic_t rcnt;
++#endif
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++#define DbgRcntInit(rw) atomic_set(&(rw)->rcnt, 0)
++#define DbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
++#define DbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
++#else
++#define DbgRcntInit(rw) /* */
++#define DbgRcntInc(rw) /* */
++#define DbgRcntDec(rw) /* */
++#endif
++
++static inline void rw_init_nolock(struct aufs_rwsem *rw)
++{
++ DbgRcntInit(rw);
++ init_rwsem(&rw->rwsem);
++}
++
++static inline void rw_init_wlock(struct aufs_rwsem *rw)
++{
++ rw_init_nolock(rw);
++ down_write(&rw->rwsem);
++}
++
++static inline void rw_init_wlock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ rw_init_nolock(rw);
++ down_write_nested(&rw->rwsem, lsc);
++}
++
++static inline void rw_read_lock(struct aufs_rwsem *rw)
++{
++ down_read(&rw->rwsem);
++ DbgRcntInc(rw);
++}
++
++static inline void rw_read_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ down_read_nested(&rw->rwsem, lsc);
++ DbgRcntInc(rw);
++}
++
++static inline void rw_read_unlock(struct aufs_rwsem *rw)
++{
++ DbgRcntDec(rw);
++ up_read(&rw->rwsem);
++}
++
++static inline void rw_dgrade_lock(struct aufs_rwsem *rw)
++{
++ DbgRcntInc(rw);
++ downgrade_write(&rw->rwsem);
++}
++
++static inline void rw_write_lock(struct aufs_rwsem *rw)
++{
++ down_write(&rw->rwsem);
++}
++
++static inline void rw_write_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
++{
++ down_write_nested(&rw->rwsem, lsc);
++}
++
++static inline void rw_write_unlock(struct aufs_rwsem *rw)
++{
++ up_write(&rw->rwsem);
++}
++
++#if 0 // why is not _nested version defined
++static inline int rw_read_trylock(struct aufs_rwsem *rw)
++{
++ int ret = down_read_trylock(&rw->rwsem);
++ if (ret)
++ DbgRcntInc(rw);
++ return ret;
++}
++
++static inline int rw_write_trylock(struct aufs_rwsem *rw)
++{
++ return down_write_trylock(&rw->rwsem);
++}
++#endif
++
++#undef DbgRcntInit
++#undef DbgRcntInc
++#undef DbgRcntDec
++
++/* to debug easier, do not make them inlined functions */
++#define RwMustNoWaiters(rw) DEBUG_ON(!list_empty(&(rw)->rwsem.wait_list))
++#define RwMustAnyLock(rw) DEBUG_ON(down_write_trylock(&(rw)->rwsem))
++#ifdef CONFIG_AUFS_DEBUG
++#define RwMustReadLock(rw) do { \
++ RwMustAnyLock(rw); \
++ DEBUG_ON(!atomic_read(&(rw)->rcnt)); \
++} while (0)
++#define RwMustWriteLock(rw) do { \
++ RwMustAnyLock(rw); \
++ DEBUG_ON(atomic_read(&(rw)->rcnt)); \
++} while (0)
++#else
++#define RwMustReadLock(rw) RwMustAnyLock(rw)
++#define RwMustWriteLock(rw) RwMustAnyLock(rw)
++#endif
++
++#define SimpleLockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_lock(param) {rw_read_lock(&(rwsem));} \
++static inline void prefix##_write_lock(param) {rw_write_lock(&(rwsem));}
++//static inline void prefix##_read_trylock(param) {rw_read_trylock(&(rwsem));}
++//static inline void prefix##_write_trylock(param) {rw_write_trylock(&(rwsem));}
++//static inline void prefix##_read_trylock_nested(param, lsc)
++//{rw_read_trylock_nested(&(rwsem, lsc));}
++//static inline void prefix##_write_trylock_nestd(param, lsc)
++//{rw_write_trylock_nested(&(rwsem), nested);}
++
++#define SimpleUnlockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_unlock(param) {rw_read_unlock(&(rwsem));} \
++static inline void prefix##_write_unlock(param) {rw_write_unlock(&(rwsem));} \
++static inline void prefix##_downgrade_lock(param) {rw_dgrade_lock(&(rwsem));}
++
++#define SimpleRwsemFuncs(prefix, param, rwsem) \
++ SimpleLockRwsemFuncs(prefix, param, rwsem); \
++ SimpleUnlockRwsemFuncs(prefix, param, rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++typedef ssize_t (*readf_t)(struct file*, char __user*, size_t, loff_t*);
++typedef ssize_t (*writef_t)(struct file*, const char __user*, size_t, loff_t*);
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
++struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
++ struct super_block *sb, aufs_bindex_t bindex);
++void fake_dm_release(struct nameidata *fake_nd);
++int au_copy_file(struct file *dst, struct file *src, loff_t len,
++ struct super_block *sb, int *sparse);
++int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode);
++int au_test_perm(struct inode *h_inode, int mask, int dlgt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MISC_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/module.c linux-2.6.22.1/fs/aufs/module.c
+--- linux-2.6.22.1.oorig/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/module.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,334 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: module.c,v 1.9 2007/04/30 05:46:32 sfjro Exp $ */
++
++//#include <linux/init.h>
++//#include <linux/kobject.h>
++#include <linux/module.h>
++//#include <linux/seq_file.h>
++//#include <linux/sysfs.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * aufs caches
++ */
++struct kmem_cache *aufs_cachep[AuCache_Last];
++static int __init create_cache(void)
++{
++#define Cache(type) kmem_cache_create(#type, sizeof(struct type), 0, \
++ SLAB_RECLAIM_ACCOUNT, NULL, NULL)
++
++ if ((aufs_cachep[AuCache_DINFO] = Cache(aufs_dinfo))
++ && (aufs_cachep[AuCache_ICNTNR] = Cache(aufs_icntnr))
++ && (aufs_cachep[AuCache_FINFO] = Cache(aufs_finfo))
++ //&& (aufs_cachep[AuCache_FINFO] = NULL)
++ && (aufs_cachep[AuCache_VDIR] = Cache(aufs_vdir))
++ && (aufs_cachep[AuCache_DEHSTR] = Cache(aufs_dehstr))
++ && (aufs_cachep[AuCache_HINOTIFY] = Cache(aufs_hinotify)))
++ return 0;
++ return -ENOMEM;
++
++#undef Cache
++}
++
++static void destroy_cache(void)
++{
++ int i;
++ for (i = 0; i < AuCache_Last; i++)
++ if (aufs_cachep[i])
++ kmem_cache_destroy(aufs_cachep[i]);
++}
++
++/* ---------------------------------------------------------------------- */
++
++char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
++int au_dir_roflags;
++extern struct file_system_type aufs_fs_type;
++
++#ifdef DbgDlgt
++#include <linux/security.h>
++#include "dbg_dlgt.c"
++#else
++#define dbg_dlgt_init() 0
++#define dbg_dlgt_fin() /* */
++#endif
++
++/*
++ * functions for module interface.
++ */
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Junjiro Okajima");
++MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
++MODULE_VERSION(AUFS_VERSION);
++
++/* it should be 'byte', but param_set_byte() prints by "%c" */
++short aufs_nwkq = AUFS_NWKQ_DEF;
++MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
++module_param_named(nwkq, aufs_nwkq, short, 0444);
++
++int sysaufs_brs = 0;
++MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/brs");
++module_param_named(brs, sysaufs_brs, int, 0444);
++
++static int __init aufs_init(void)
++{
++ int err, i;
++ char *p;
++
++ //sbinfo->si_xino is atomic_long_t
++ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
++
++#ifdef CONFIG_AUFS_DEBUG
++ {
++ struct aufs_destr destr;
++ destr.len = -1;
++ DEBUG_ON(destr.len < NAME_MAX);
++ }
++
++#ifdef CONFIG_4KSTACKS
++ printk("CONFIG_4KSTACKS is defined.\n");
++#endif
++#if 0 // verbose debug
++ {
++ union {
++ struct aufs_branch *br;
++ struct aufs_dinfo *di;
++ struct aufs_finfo *fi;
++ struct aufs_iinfo *ii;
++ struct aufs_hinode *hi;
++ struct aufs_sbinfo *si;
++ struct aufs_destr *destr;
++ struct aufs_de *de;
++ struct aufs_wh *wh;
++ struct aufs_vdir *vd;
++ } u;
++
++ printk("br{"
++ "xino %d, readf %d, writef %d, "
++ "id %d, perm %d, mnt %d, count %d, "
++ "wh_sem %d, wh %d, run %d} %d\n",
++ offsetof(typeof(*u.br), br_xino),
++ offsetof(typeof(*u.br), br_xino_read),
++ offsetof(typeof(*u.br), br_xino_write),
++ offsetof(typeof(*u.br), br_id),
++ offsetof(typeof(*u.br), br_perm),
++ offsetof(typeof(*u.br), br_mnt),
++ offsetof(typeof(*u.br), br_count),
++ offsetof(typeof(*u.br), br_wh_rwsem),
++ offsetof(typeof(*u.br), br_wh),
++ offsetof(typeof(*u.br), br_wh_running),
++ sizeof(*u.br));
++ printk("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, "
++ "bdiropq %d, hdentry %d, reval %d} %d\n",
++ offsetof(typeof(*u.di), di_generation),
++ offsetof(typeof(*u.di), di_rwsem),
++ offsetof(typeof(*u.di), di_bstart),
++ offsetof(typeof(*u.di), di_bend),
++ offsetof(typeof(*u.di), di_bwh),
++ offsetof(typeof(*u.di), di_bdiropq),
++ offsetof(typeof(*u.di), di_hdentry),
++ offsetof(typeof(*u.di), di_reval),
++ sizeof(*u.di));
++ printk("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, "
++ "h_vm_ops %d, vdir_cach %d} %d\n",
++ offsetof(typeof(*u.fi), fi_generation),
++ offsetof(typeof(*u.fi), fi_rwsem),
++ offsetof(typeof(*u.fi), fi_hfile),
++ offsetof(typeof(*u.fi), fi_bstart),
++ offsetof(typeof(*u.fi), fi_bend),
++ offsetof(typeof(*u.fi), fi_h_vm_ops),
++ offsetof(typeof(*u.fi), fi_vdir_cache),
++ sizeof(*u.fi));
++ printk("ii{rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} "
++ "%d\n",
++ offsetof(typeof(*u.ii), ii_rwsem),
++ offsetof(typeof(*u.ii), ii_bstart),
++ offsetof(typeof(*u.ii), ii_bend),
++ offsetof(typeof(*u.ii), ii_hinode),
++ offsetof(typeof(*u.ii), ii_vdir),
++ sizeof(*u.ii));
++ printk("hi{inode %d, id %d, notify %d} %d\n",
++ offsetof(typeof(*u.hi), hi_inode),
++ offsetof(typeof(*u.hi), hi_id),
++ offsetof(typeof(*u.hi), hi_notify),
++ sizeof(*u.hi));
++ printk("si{rwsem %d, gen %d, "
++ "failed_refresh %d, "
++ "bend %d, last id %d, br %d, "
++ "flags %d, "
++ "xino %d, "
++ "rdcache %d, "
++ "dirwh %d, "
++ "pl_lock %d, pl %d, "
++ "kobj %d} %d\n",
++ offsetof(typeof(*u.si), si_rwsem),
++ offsetof(typeof(*u.si), si_generation),
++ -1,//offsetof(typeof(*u.si), si_failed_refresh_dirs),
++ offsetof(typeof(*u.si), si_bend),
++ offsetof(typeof(*u.si), si_last_br_id),
++ offsetof(typeof(*u.si), si_branch),
++ offsetof(typeof(*u.si), si_flags),
++ offsetof(typeof(*u.si), si_xino),
++ offsetof(typeof(*u.si), si_rdcache),
++ offsetof(typeof(*u.si), si_dirwh),
++ offsetof(typeof(*u.si), si_plink_lock),
++ offsetof(typeof(*u.si), si_plink),
++ offsetof(typeof(*u.si), si_kobj),
++ sizeof(*u.si));
++ printk("destr{len %d, name %d} %d\n",
++ offsetof(typeof(*u.destr), len),
++ offsetof(typeof(*u.destr), name),
++ sizeof(*u.destr));
++ printk("de{ino %d, type %d, str %d} %d\n",
++ offsetof(typeof(*u.de), de_ino),
++ offsetof(typeof(*u.de), de_type),
++ offsetof(typeof(*u.de), de_str),
++ sizeof(*u.de));
++ printk("wh{hash %d, bindex %d, str %d} %d\n",
++ offsetof(typeof(*u.wh), wh_hash),
++ offsetof(typeof(*u.wh), wh_bindex),
++ offsetof(typeof(*u.wh), wh_str),
++ sizeof(*u.wh));
++ printk("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n",
++ offsetof(typeof(*u.vd), vd_deblk),
++ offsetof(typeof(*u.vd), vd_nblk),
++ offsetof(typeof(*u.vd), vd_last),
++ offsetof(typeof(*u.vd), vd_version),
++ offsetof(typeof(*u.vd), vd_jiffy),
++ sizeof(*u.vd));
++ }
++#endif
++#endif
++
++ p = au_esc_chars;
++ for (i = 1; i <= ' '; i++)
++ *p++ = i;
++ *p++ = '\\';
++ *p++ = '\x7f';
++ *p = 0;
++
++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
++#ifndef CONFIG_AUFS_SYSAUFS
++ sysaufs_brs = 0;
++#endif
++
++ err = -EINVAL;
++ if (unlikely(aufs_nwkq <= 0))
++ goto out;
++ err = create_cache();
++ if (unlikely(err))
++ goto out;
++ err = sysaufs_init();
++ if (unlikely(err))
++ goto out_cache;
++ err = au_wkq_init();
++ if (unlikely(err))
++ goto out_kobj;
++ err = au_inotify_init();
++ if (unlikely(err))
++ goto out_wkq;
++ err = dbg_dlgt_init();
++ if (unlikely(err))
++ goto out_inotify;
++ err = register_filesystem(&aufs_fs_type);
++ if (unlikely(err))
++ goto out_dlgt;
++ printk(AUFS_NAME " " AUFS_VERSION "\n");
++ return 0; /* success */
++
++ out_dlgt:
++ dbg_dlgt_fin();
++ out_inotify:
++ au_inotify_fin();
++ out_wkq:
++ au_wkq_fin();
++ out_kobj:
++ sysaufs_fin();
++ out_cache:
++ destroy_cache();
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static void __exit aufs_exit(void)
++{
++ unregister_filesystem(&aufs_fs_type);
++ dbg_dlgt_fin();
++ au_inotify_fin();
++ au_wkq_fin();
++ sysaufs_fin();
++ destroy_cache();
++}
++
++module_init(aufs_init);
++module_exit(aufs_exit);
++
++/* ---------------------------------------------------------------------- */
++
++// fake Kconfig
++#if 1
++#ifdef CONFIG_AUFS_HINOTIFY
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_HINOTIFY is supported in linux-2.6.18 and later.
++#endif
++#ifndef CONFIG_INOTIFY
++#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
++#endif
++#endif
++
++#if AUFS_BRANCH_MAX > 511 && BITS_PER_LONG == 64 && PAGE_SIZE == 4096
++#warning For 4k pagesize and 64bit environment, \
++ CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
++#endif
++
++#ifdef CONFIG_AUFS_SYSAUFS
++#ifndef CONFIG_SYSFS
++#error CONFIG_AUFS_SYSAUFS requires CONFIG_SYSFS.
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_SYSAUFS requires linux-2.6.18 and later.
++#endif
++#endif
++
++#ifdef CONFIG_AUFS_EXPORT
++#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
++#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#error CONFIG_AUFS_EXPORT requires linux-2.6.18 and later.
++#endif
++#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
++#error need CONFIG_EXPORTFS=y to link aufs statically with CONFIG_AUFS_EXPORT
++#endif
++#endif
++
++#ifdef CONFIG_DEBUG_PROVE_LOCKING
++#if MAX_LOCKDEP_SUBCLASSES < AuLsc_End
++#warning lockdep will not work since aufs uses deeper locks.
++#endif
++#endif
++
++#ifdef CONFIG_AUFS_COMPAT
++#warning CONFIG_AUFS_COMPAT will be removed in the near future.
++#endif
++
++#endif
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/module.h linux-2.6.22.1/fs/aufs/module.h
+--- linux-2.6.22.1.oorig/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/module.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: module.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_MODULE_H__
++#define __AUFS_MODULE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/slab.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* module parameters */
++extern short aufs_nwkq;
++extern int sysaufs_brs;
++
++/* ---------------------------------------------------------------------- */
++
++extern char au_esc_chars[];
++extern int au_dir_roflags;
++
++/* kmem cache */
++enum {AuCache_DINFO, AuCache_ICNTNR, AuCache_FINFO, AuCache_VDIR,
++ AuCache_DEHSTR, AuCache_HINOTIFY, AuCache_Last};
++extern struct kmem_cache *aufs_cachep[];
++
++#define CacheFuncs(name, index) \
++static inline void *cache_alloc_##name(void) \
++{return kmem_cache_alloc(aufs_cachep[index], GFP_KERNEL);} \
++static inline void cache_free_##name(void *p) \
++{kmem_cache_free(aufs_cachep[index], p);}
++
++CacheFuncs(dinfo, AuCache_DINFO);
++CacheFuncs(icntnr, AuCache_ICNTNR);
++CacheFuncs(finfo, AuCache_FINFO);
++CacheFuncs(vdir, AuCache_VDIR);
++CacheFuncs(dehstr, AuCache_DEHSTR);
++CacheFuncs(hinotify, AuCache_HINOTIFY);
++
++#undef CacheFuncs
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MODULE_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/opts.c linux-2.6.22.1/fs/aufs/opts.c
+--- linux-2.6.22.1.oorig/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/opts.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,1043 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: opts.c,v 1.34 2007/05/14 03:40:27 sfjro Exp $ */
++
++#include <asm/types.h> // a distribution requires
++#include <linux/parser.h>
++#include "aufs.h"
++
++enum {
++ Opt_br,
++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
++ Opt_idel, Opt_imod,
++ Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash,
++ Opt_xino, Opt_zxino, Opt_noxino,
++ Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
++ Opt_udba,
++ Opt_diropq_a, Opt_diropq_w,
++ Opt_warn_perm, Opt_nowarn_perm,
++ Opt_findrw_dir, Opt_findrw_br,
++ Opt_coo,
++ Opt_dlgt, Opt_nodlgt,
++ Opt_tail, Opt_ignore, Opt_err
++};
++
++static match_table_t options = {
++ {Opt_br, "br=%s"},
++ {Opt_br, "br:%s"},
++
++ {Opt_add, "add=%d:%s"},
++ {Opt_add, "add:%d:%s"},
++ {Opt_add, "ins=%d:%s"},
++ {Opt_add, "ins:%d:%s"},
++ {Opt_append, "append=%s"},
++ {Opt_append, "append:%s"},
++ {Opt_prepend, "prepend=%s"},
++ {Opt_prepend, "prepend:%s"},
++
++ {Opt_del, "del=%s"},
++ {Opt_del, "del:%s"},
++ //{Opt_idel, "idel:%d"},
++ {Opt_mod, "mod=%s"},
++ {Opt_mod, "mod:%s"},
++ //{Opt_imod, "imod:%d:%s"},
++
++ {Opt_dirwh, "dirwh=%d"},
++ {Opt_dirwh, "dirwh:%d"},
++
++ {Opt_xino, "xino=%s"},
++ {Opt_xino, "xino:%s"},
++ {Opt_noxino, "noxino"},
++ //{Opt_zxino, "zxino=%s"},
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++ {Opt_plink, "plink"},
++ {Opt_noplink, "noplink"},
++#ifdef CONFIG_AUFS_DEBUG
++ {Opt_list_plink, "list_plink"},
++#endif
++ {Opt_clean_plink, "clean_plink"},
++#endif
++
++ {Opt_udba, "udba=%s"},
++
++ {Opt_diropq_a, "diropq=always"},
++ {Opt_diropq_a, "diropq=a"},
++ {Opt_diropq_w, "diropq=whiteouted"},
++ {Opt_diropq_w, "diropq=w"},
++
++ {Opt_warn_perm, "warn_perm"},
++ {Opt_nowarn_perm, "nowarn_perm"},
++
++#ifdef CONFIG_AUFS_DLGT
++ {Opt_dlgt, "dlgt"},
++ {Opt_nodlgt, "nodlgt"},
++#endif
++
++ {Opt_rdcache, "rdcache=%d"},
++ {Opt_rdcache, "rdcache:%d"},
++#if 0
++ {Opt_findrw_dir, "findrw=dir"},
++ {Opt_findrw_br, "findrw=br"},
++
++ {Opt_coo, "coo=%s"},
++
++ {Opt_deblk, "deblk=%d"},
++ {Opt_deblk, "deblk:%d"},
++ {Opt_nhash, "nhash=%d"},
++ {Opt_nhash, "nhash:%d"},
++#endif
++
++ {Opt_br, "dirs=%s"},
++ {Opt_ignore, "debug=%d"},
++ {Opt_ignore, "delete=whiteout"},
++ {Opt_ignore, "delete=all"},
++ {Opt_ignore, "imap=%s"},
++
++ {Opt_err, NULL}
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define RW "rw"
++#define RO "ro"
++#define WH "wh"
++#define RR "rr"
++#define NoLinkWH "nolwh"
++
++static match_table_t brperms = {
++ {AuBr_RR, RR},
++ {AuBr_RO, RO},
++ {AuBr_RW, RW},
++
++ {AuBr_RRWH, RR "+" WH},
++ {AuBr_ROWH, RO "+" WH},
++ {AuBr_RWNoLinkWH, RW "+" NoLinkWH},
++
++ {AuBr_ROWH, "nfsro"},
++ {AuBr_RO, NULL}
++};
++
++static int br_perm_val(char *perm)
++{
++ int val;
++ substring_t args[MAX_OPT_ARGS];
++
++ DEBUG_ON(!perm || !*perm);
++ LKTRTrace("perm %s\n", perm);
++ val = match_token(perm, brperms, args);
++ TraceErr(val);
++ return val;
++}
++
++int br_perm_str(char *p, unsigned int len, int brperm)
++{
++ struct match_token *bp = brperms;
++
++ LKTRTrace("len %d, 0x%x\n", len, brperm);
++
++ while (bp->pattern) {
++ if (bp->token == brperm) {
++ if (strlen(bp->pattern) < len) {
++ strcpy(p, bp->pattern);
++ return 0;
++ } else
++ return -E2BIG;
++ }
++ bp++;
++ }
++
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t udbalevel = {
++ {AuFlag_UDBA_REVAL, "reval"},
++#ifdef CONFIG_AUFS_HINOTIFY
++ {AuFlag_UDBA_INOTIFY, "inotify"},
++#endif
++ {AuFlag_UDBA_NONE, "none"},
++ {-1, NULL}
++};
++
++static int udba_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++ return match_token(str, udbalevel, args);
++}
++
++au_parser_pattern_t udba_str(int udba)
++{
++ struct match_token *p = udbalevel;
++ while (p->pattern) {
++ if (p->token == udba)
++ return p->pattern;
++ p++;
++ }
++ BUG();
++ return "??";
++}
++
++void udba_set(struct super_block *sb, unsigned int flg)
++{
++ au_flag_clr(sb, AuMask_UDBA);
++ au_flag_set(sb, flg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t coolevel = {
++ {AuFlag_COO_LEAF, "leaf"},
++ {AuFlag_COO_ALL, "all"},
++ {AuFlag_COO_NONE, "none"},
++ {-1, NULL}
++};
++
++#if 0
++static int coo_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++ return match_token(str, coolevel, args);
++}
++#endif
++
++au_parser_pattern_t coo_str(int coo)
++{
++ struct match_token *p = coolevel;
++ while (p->pattern) {
++ if (p->token == coo)
++ return p->pattern;
++ p++;
++ }
++ BUG();
++ return "??";
++}
++static void coo_set(struct super_block *sb, unsigned int flg)
++{
++ au_flag_clr(sb, AuMask_COO);
++ au_flag_set(sb, flg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
++
++#ifdef CONFIG_AUFS_DEBUG
++static void dump_opts(struct opts *opts)
++{
++ /* reduce stack space */
++ union {
++ struct opt_add *add;
++ struct opt_del *del;
++ struct opt_mod *mod;
++ struct opt_xino *xino;
++ } u;
++ struct opt *opt;
++
++ TraceEnter();
++
++ opt = opts->opt;
++ while (/* opt < opts_tail && */ opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ u.add = &opt->add;
++ LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ u.del = &opt->del;
++ LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ u.mod = &opt->mod;
++ LKTRTrace("mod {%s, 0x%x, %p}\n",
++ u.mod->path, u.mod->perm, u.mod->h_root);
++ break;
++ case Opt_append:
++ u.add = &opt->add;
++ LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_prepend:
++ u.add = &opt->add;
++ LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->path, u.add->perm,
++ u.add->nd.dentry);
++ break;
++ case Opt_dirwh:
++ LKTRTrace("dirwh %d\n", opt->dirwh);
++ break;
++ case Opt_rdcache:
++ LKTRTrace("rdcache %d\n", opt->rdcache);
++ break;
++ case Opt_xino:
++ u.xino = &opt->xino;
++ LKTRTrace("xino {%s %.*s}\n",
++ u.xino->path, DLNPair(u.xino->file->f_dentry));
++ break;
++ case Opt_noxino:
++ LKTRLabel(noxino);
++ break;
++ case Opt_plink:
++ LKTRLabel(plink);
++ break;
++ case Opt_noplink:
++ LKTRLabel(noplink);
++ break;
++ case Opt_list_plink:
++ LKTRLabel(list_plink);
++ break;
++ case Opt_clean_plink:
++ LKTRLabel(clean_plink);
++ break;
++ case Opt_udba:
++ LKTRTrace("udba %d, %s\n",
++ opt->udba, udba_str(opt->udba));
++ break;
++ case Opt_diropq_a:
++ LKTRLabel(diropq_a);
++ break;
++ case Opt_diropq_w:
++ LKTRLabel(diropq_w);
++ break;
++ case Opt_warn_perm:
++ LKTRLabel(warn_perm);
++ break;
++ case Opt_nowarn_perm:
++ LKTRLabel(nowarn_perm);
++ break;
++ case Opt_dlgt:
++ LKTRLabel(dlgt);
++ break;
++ case Opt_nodlgt:
++ LKTRLabel(nodlgt);
++ break;
++ case Opt_coo:
++ LKTRTrace("coo %d, %s\n", opt->coo, coo_str(opt->coo));
++ break;
++ default:
++ BUG();
++ }
++ opt++;
++ }
++}
++#else
++#define dump_opts(opts) /* */
++#endif
++
++void au_free_opts(struct opts *opts)
++{
++ struct opt *opt;
++
++ TraceEnter();
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ case Opt_append:
++ case Opt_prepend:
++ path_release(&opt->add.nd);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ dput(opt->del.h_root);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ dput(opt->mod.h_root);
++ break;
++ case Opt_xino:
++ fput(opt->xino.file);
++ break;
++ }
++ opt++;
++ }
++}
++
++static int opt_add(struct opt *opt, char *opt_str, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct opt_add *add = &opt->add;
++ char *p;
++
++ LKTRTrace("%s, b%d\n", opt_str, bindex);
++
++ add->bindex = bindex;
++ add->perm = AuBr_RO;
++ if (!bindex && !(sb->s_flags & MS_RDONLY))
++ add->perm = AuBr_RW;
++#ifdef CONFIG_AUFS_COMPAT
++ add->perm = AuBr_RW;
++#endif
++ add->path = opt_str;
++ p = strchr(opt_str, '=');
++ if (unlikely(p)) {
++ *p++ = 0;
++ if (*p)
++ add->perm = br_perm_val(p);
++ }
++
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(add->path, lkup_dirflags, &add->nd);
++ //err = -1;
++ if (!err) {
++ opt->type = Opt_add;
++ goto out;
++ }
++ Err("lookup failed %s (%d)\n", add->path, err);
++ err = -EINVAL;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* called without aufs lock */
++int au_parse_opts(struct super_block *sb, char *str, struct opts *opts)
++{
++ int err, n;
++ struct dentry *root;
++ struct opt *opt, *opt_tail;
++ char *opt_str;
++ substring_t args[MAX_OPT_ARGS];
++ aufs_bindex_t bindex;
++ struct nameidata nd;
++ /* reduce stack space */
++ union {
++ struct opt_del *del;
++ struct opt_mod *mod;
++ struct opt_xino *xino;
++ } u;
++ struct file *file;
++
++ LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
++
++ root = sb->s_root;
++ err = 0;
++ bindex = 0;
++ opt = opts->opt;
++ opt_tail = opt + opts->max_opt - 1;
++ opt->type = Opt_tail;
++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
++ int token, skipped;
++ char *p;
++ err = -EINVAL;
++ token = match_token(opt_str, options, args);
++ LKTRTrace("%s, token %d, args[0]{%p, %p}\n",
++ opt_str, token, args[0].from, args[0].to);
++
++ skipped = 0;
++ switch (token) {
++ case Opt_br:
++ err = 0;
++ while (!err && (opt_str = strsep(&args[0].from, ":"))
++ && *opt_str) {
++ err = opt_add(opt, opt_str, sb, bindex++);
++ //if (LktrCond) err = -1;
++ if (unlikely(!err && ++opt > opt_tail)) {
++ err = -E2BIG;
++ break;
++ }
++ opt->type = Opt_tail;
++ skipped = 1;
++ }
++ break;
++ case Opt_add:
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ err = opt_add(opt, args[1].from, sb, bindex);
++ break;
++ case Opt_append:
++ case Opt_prepend:
++ err = opt_add(opt, args[0].from, sb, /*dummy bindex*/1);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_del:
++ u.del = &opt->del;
++ u.del->path = args[0].from;
++ LKTRTrace("del path %s\n", u.del->path);
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(u.del->path, lkup_dirflags, &nd);
++ if (unlikely(err)) {
++ Err("lookup failed %s (%d)\n", u.del->path, err);
++ break;
++ }
++ u.del->h_root = dget(nd.dentry);
++ path_release(&nd);
++ opt->type = token;
++ break;
++#if 0
++ case Opt_idel:
++ u.del = &opt->del;
++ u.del->path = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (bindex < 0 || sbend(sb) < bindex) {
++ Err("out of bounds, %d\n", bindex);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++ }
++ err = 0;
++ u.del->h_root = dget(au_h_dptr_i(root, bindex));
++ opt->type = token;
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++#endif
++
++ case Opt_mod:
++ u.mod = &opt->mod;
++ u.mod->path = args[0].from;
++ p = strchr(u.mod->path, '=');
++ if (unlikely(!p)) {
++ Err("no permssion %s\n", opt_str);
++ break;
++ }
++ *p++ = 0;
++ u.mod->perm = br_perm_val(p);
++ LKTRTrace("mod path %s, perm 0x%x, %s\n",
++ u.mod->path, u.mod->perm, p);
++ // LSM may detect it
++ // do not superio.
++ err = path_lookup(u.mod->path, lkup_dirflags, &nd);
++ if (unlikely(err)) {
++ Err("lookup failed %s (%d)\n", u.mod->path, err);
++ break;
++ }
++ u.mod->h_root = dget(nd.dentry);
++ path_release(&nd);
++ opt->type = token;
++ break;
++#if 0
++ case Opt_imod:
++ u.mod = &opt->mod;
++ u.mod->path = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ Err("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (bindex < 0 || sbend(sb) < bindex) {
++ Err("out of bounds, %d\n", bindex);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++ }
++ u.mod->perm = br_perm_val(args[1].from);
++ LKTRTrace("mod path %s, perm 0x%x, %s\n",
++ u.mod->path, u.mod->perm, args[1].from);
++ err = 0;
++ u.mod->h_root = dget(au_h_dptr_i(root, bindex));
++ opt->type = token;
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ break;
++#endif
++ case Opt_xino:
++ u.xino = &opt->xino;
++ file = xino_create(sb, args[0].from, /*silent*/0,
++ /*parent*/NULL);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ break;
++ err = -EINVAL;
++ if (unlikely(file->f_dentry->d_sb == sb)) {
++ fput(file);
++ Err("%s must be outside\n", args[0].from);
++ break;
++ }
++ err = 0;
++ u.xino->file = file;
++ u.xino->path = args[0].from;
++ opt->type = token;
++ break;
++
++ case Opt_dirwh:
++ if (unlikely(match_int(&args[0], &opt->dirwh)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_rdcache:
++ if (unlikely(match_int(&args[0], &opt->rdcache)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_noxino:
++ case Opt_plink:
++ case Opt_noplink:
++ case Opt_list_plink:
++ case Opt_clean_plink:
++ case Opt_diropq_a:
++ case Opt_diropq_w:
++ case Opt_warn_perm:
++ case Opt_nowarn_perm:
++ case Opt_dlgt:
++ case Opt_nodlgt:
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_udba:
++ opt->udba = udba_val(args[0].from);
++ if (opt->udba >= 0) {
++ err = 0;
++ opt->type = token;
++ }
++ break;
++
++#if 0
++ case Opt_coo:
++ opt->coo = coo_val(args[0].from);
++ if (opt->coo >= 0) {
++ err = 0;
++ opt->type = token;
++ }
++ break;
++#endif
++
++ case Opt_ignore:
++#ifndef CONFIG_AUFS_COMPAT
++ Warn("ignored %s\n", opt_str);
++#endif
++ skipped = 1;
++ err = 0;
++ break;
++ case Opt_err:
++ Err("unknown option %s\n", opt_str);
++ break;
++ }
++
++ if (!err && !skipped) {
++ if (unlikely(++opt > opt_tail)) {
++ err = -E2BIG;
++ opt--;
++ opt->type = Opt_tail;
++ break;
++ }
++ opt->type = Opt_tail;
++ }
++ }
++
++ dump_opts(opts);
++ if (unlikely(err))
++ au_free_opts(opts);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns,
++ * plus: processed without an error
++ * zero: unprocessed
++ */
++static int au_do_opt_simple(struct super_block *sb, struct opt *opt,
++ int remount, unsigned int *given)
++{
++ int err;
++ struct aufs_sbinfo *sbinfo = stosi(sb);
++
++ TraceEnter();
++
++ err = 1; /* handled */
++ switch (opt->type) {
++ case Opt_udba:
++ udba_set(sb, opt->udba);
++ *given |= opt->udba;
++ break;
++
++ case Opt_plink:
++ au_flag_set(sb, AuFlag_PLINK);
++ *given |= AuFlag_PLINK;
++ break;
++ case Opt_noplink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_put_plink(sb);
++ au_flag_clr(sb, AuFlag_PLINK);
++ *given |= AuFlag_PLINK;
++ break;
++ case Opt_list_plink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_list_plink(sb);
++ break;
++ case Opt_clean_plink:
++ if (au_flag_test(sb, AuFlag_PLINK))
++ au_put_plink(sb);
++ break;
++
++ case Opt_diropq_a:
++ au_flag_set(sb, AuFlag_ALWAYS_DIROPQ);
++ *given |= AuFlag_ALWAYS_DIROPQ;
++ break;
++ case Opt_diropq_w:
++ au_flag_clr(sb, AuFlag_ALWAYS_DIROPQ);
++ *given |= AuFlag_ALWAYS_DIROPQ;
++ break;
++
++ case Opt_dlgt:
++ au_flag_set(sb, AuFlag_DLGT);
++ *given |= AuFlag_DLGT;
++ break;
++ case Opt_nodlgt:
++ au_flag_clr(sb, AuFlag_DLGT);
++ *given |= AuFlag_DLGT;
++ break;
++
++ case Opt_warn_perm:
++ au_flag_set(sb, AuFlag_WARN_PERM);
++ *given |= AuFlag_WARN_PERM;
++ break;
++ case Opt_nowarn_perm:
++ au_flag_clr(sb, AuFlag_WARN_PERM);
++ *given |= AuFlag_WARN_PERM;
++ break;
++
++ case Opt_coo:
++ coo_set(sb, opt->coo);
++ *given |= opt->coo;
++ break;
++
++ case Opt_dirwh:
++ sbinfo->si_dirwh = opt->dirwh;
++ break;
++
++ case Opt_rdcache:
++ sbinfo->si_rdcache = opt->rdcache * HZ;
++ break;
++
++ default:
++ err = 0;
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns tri-state.
++ * plus: processed without an error
++ * zero: unprocessed
++ * minus: error
++ */
++static int au_do_opt_br(struct super_block *sb, struct opt *opt, int remount,
++ int *do_refresh)
++{
++ int err;
++
++ TraceEnter();
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_append:
++ opt->add.bindex = sbend(sb) + 1;
++ goto add;
++ case Opt_prepend:
++ opt->add.bindex = 0;
++ add:
++ case Opt_add:
++ err = br_add(sb, &opt->add, remount);
++ if (!err)
++ *do_refresh = err = 1;
++ break;
++
++ case Opt_del:
++ case Opt_idel:
++ err = br_del(sb, &opt->del, remount);
++ if (!err)
++ *do_refresh = err = 1;
++ break;
++
++ case Opt_mod:
++ case Opt_imod:
++ err = br_mod(sb, &opt->mod, remount, do_refresh);
++ if (!err)
++ err = 1;
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int au_do_opt_xino(struct super_block *sb, struct opt *opt, int remount,
++ struct opt_xino **opt_xino)
++{
++ int err;
++
++ TraceEnter();
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_xino:
++ err = xino_set(sb, &opt->xino, remount);
++ if (!err)
++ *opt_xino = &opt->xino;
++ break;
++ case Opt_noxino:
++ err = xino_clr(sb);
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int verify_opts(struct super_block *sb, int remount)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct aufs_branch *br;
++ struct dentry *root;
++ struct inode *dir;
++ unsigned int do_plink;
++
++ TraceEnter();
++
++ if (unlikely(!(sb->s_flags & MS_RDONLY)
++ && !br_writable(sbr_perm(sb, 0))))
++ Warn("first branch should be rw\n");
++
++ err = 0;
++ root = sb->s_root;
++ dir = sb->s_root->d_inode;
++ do_plink = au_flag_test(sb, AuFlag_PLINK);
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ struct inode *h_dir;
++ int skip;
++
++ skip = 0;
++ h_dir = au_h_iptr_i(dir, bindex);
++ br = stobr(sb, bindex);
++ br_wh_read_lock(br);
++ switch (br->br_perm) {
++ case AuBr_RR:
++ case AuBr_RO:
++ case AuBr_RRWH:
++ case AuBr_ROWH:
++ skip = (!br->br_wh && !br->br_plink);
++ break;
++
++ case AuBr_RWNoLinkWH:
++ skip = !br->br_wh;
++ if (skip) {
++ if (do_plink)
++ skip = !!br->br_plink;
++ else
++ skip = !br->br_plink;
++ }
++ break;
++
++ case AuBr_RW:
++ skip = !!br->br_wh;
++ if (skip) {
++ if (do_plink)
++ skip = !!br->br_plink;
++ else
++ skip = !br->br_plink;
++ }
++ break;
++
++ default:
++ BUG();
++ }
++ br_wh_read_unlock(br);
++
++ if (skip)
++ continue;
++
++ hdir_lock(h_dir, dir, bindex);
++ br_wh_write_lock(br);
++ err = init_wh(au_h_dptr_i(root, bindex), br,
++ au_nfsmnt(sb, bindex), sb);
++ br_wh_write_unlock(br);
++ hdir_unlock(h_dir, dir, bindex);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++int au_do_opts_mount(struct super_block *sb, struct opts *opts)
++{
++ int err, do_refresh;
++ struct inode *dir;
++ struct opt *opt;
++ unsigned int flags, given;
++ struct opt_xino *opt_xino;
++ aufs_bindex_t bend, bindex;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DiMustWriteLock(sb->s_root);
++ dir = sb->s_root->d_inode;
++ IiMustWriteLock(dir);
++
++ err = 0;
++ given = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_do_opt_simple(sb, opt++, /*remount*/0, &given);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ /* disable them temporary */
++ flags = au_flag_test(sb, AuFlag_XINO | AuMask_UDBA | AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_XINO | AuFlag_DLGT);
++ udba_set(sb, AuFlag_UDBA_REVAL);
++
++ do_refresh = 0;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ bend = sbend(sb);
++ if (unlikely(bend < 0)) {
++ err = -EINVAL;
++ Err("no branches\n");
++ goto out;
++ }
++
++ if (flags & AuFlag_XINO)
++ au_flag_set(sb, AuFlag_XINO);
++ opt = opts->opt;
++ while (!err && opt->type != Opt_tail)
++ err = au_do_opt_xino(sb, opt++, /*remount*/0, &opt_xino);
++ if (unlikely(err))
++ goto out;
++
++ //todo: test this error case.
++ err = verify_opts(sb, /*remount*/0);
++ DEBUG_ON(err);
++ if (unlikely(err))
++ goto out;
++
++ /* enable xino */
++ if (au_flag_test(sb, AuFlag_XINO) && !opt_xino) {
++ struct file *xino_file = xino_def(sb);
++ err = PTR_ERR(xino_file);
++ if (IS_ERR(xino_file))
++ goto out;
++
++ err = 0;
++ for (bindex = 0; !err && bindex <= bend; bindex++)
++ err = xino_init(sb, bindex, xino_file,
++ /*do_test*/bindex);
++ fput(xino_file);
++ if (unlikely(err))
++ goto out;
++ }
++
++ /* restore hinotify */
++ udba_set(sb, flags & AuMask_UDBA);
++ if (flags & AuFlag_UDBA_INOTIFY)
++ au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AUFS_HI_XINO);
++
++ /* restore dlgt */
++ if (flags & AuFlag_DLGT)
++ au_flag_set(sb, AuFlag_DLGT);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++int au_do_opts_remount(struct super_block *sb, struct opts *opts,
++ int *do_refresh, unsigned int *given)
++{
++ int err, rerr;
++ struct inode *dir;
++ struct opt_xino *opt_xino;
++ struct opt *opt;
++ unsigned int dlgt;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DiMustWriteLock(sb->s_root);
++ dir = sb->s_root->d_inode;
++ IiMustWriteLock(dir);
++ //DEBUG_ON(au_flag_test(sb, AuFlag_UDBA_INOTIFY));
++
++ err = 0;
++ *do_refresh = 0;
++ *given = 0;
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail) {
++ err = au_do_opt_simple(sb, opt, /*remount*/1, given);
++
++ /* disable it temporary */
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_DLGT);
++
++ if (!err)
++ err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh);
++ if (!err)
++ err = au_do_opt_xino(sb, opt, /*remount*/1, &opt_xino);
++
++ /* restore it */
++ au_flag_set(sb, dlgt);
++ opt++;
++ }
++ if (err > 0)
++ err = 0;
++ TraceErr(err);
++
++ /* go on if err */
++
++ //todo: test this error case.
++ au_flag_clr(sb, AuFlag_DLGT);
++ rerr = verify_opts(sb, /*remount*/1);
++ au_flag_set(sb, dlgt);
++
++ /* they are handled by the caller */
++ if (!*do_refresh)
++ *do_refresh = !!((*given & AuMask_UDBA)
++ || au_flag_test(sb, AuFlag_XINO));
++
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/opts.h linux-2.6.22.1/fs/aufs/opts.h
+--- linux-2.6.22.1.oorig/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/opts.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,96 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: opts.h,v 1.13 2007/05/14 06:27:18 sfjro Exp $ */
++
++#ifndef __AUFS_OPTS_H__
++#define __AUFS_OPTS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++typedef const char* au_parser_pattern_t;
++#else
++typedef char* au_parser_pattern_t;
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++struct opt_add {
++ aufs_bindex_t bindex;
++ char *path;
++ int perm;
++ struct nameidata nd;
++};
++
++struct opt_del {
++ char *path;
++ struct dentry *h_root;
++};
++
++struct opt_mod {
++ char *path;
++ int perm;
++ struct dentry *h_root;
++};
++
++struct opt_xino {
++ char *path;
++ struct file *file;
++};
++
++struct opt {
++ int type;
++ union {
++ struct opt_xino xino;
++ struct opt_add add;
++ struct opt_del del;
++ struct opt_mod mod;
++ int dirwh;
++ int rdcache;
++ int deblk;
++ int nhash;
++ int udba;
++ int coo;
++ };
++};
++
++struct opts {
++ struct opt *opt;
++ int max_opt;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int br_perm_str(char *p, unsigned int len, int brperm);
++au_parser_pattern_t udba_str(int udba);
++void udba_set(struct super_block *sb, unsigned int flg);
++//au_parser_pattern_t coo_str(int coo);
++void au_free_opts(struct opts *opts);
++int au_parse_opts(struct super_block *sb, char *str, struct opts *opts);
++int au_do_opts_mount(struct super_block *sb, struct opts *opts);
++int au_do_opts_remount(struct super_block *sb, struct opts *opts,
++ int *do_refresh, unsigned int *given);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_OPTS_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/plink.c linux-2.6.22.1/fs/aufs/plink.c
+--- linux-2.6.22.1.oorig/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/plink.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,331 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: plink.c,v 1.4 2007/05/14 03:39:10 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct pseudo_link {
++ struct list_head list;
++ struct inode *inode;
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++void au_list_plink(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ TraceEnter();
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list)
++ Dbg("%lu\n", plink->inode->i_ino);
++ spin_unlock(&sbinfo->si_plink_lock);
++}
++#endif
++
++int au_is_plinked(struct super_block *sb, struct inode *inode)
++{
++ int found;
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ found = 0;
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list)
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ spin_unlock(&sbinfo->si_plink_lock);
++ return found;
++}
++
++// 20 is max digits length of ulong 64
++#define PLINK_NAME_LEN ((20 + 1) * 2)
++
++static int plink_name(char *name, int len, struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ int rlen;
++ struct inode *h_inode;
++
++ LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
++ DEBUG_ON(len != PLINK_NAME_LEN);
++ h_inode = au_h_iptr_i(inode, bindex);
++ DEBUG_ON(!h_inode);
++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
++ DEBUG_ON(rlen >= len);
++ return rlen;
++}
++
++struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode)
++{
++ struct dentry *h_dentry, *h_parent;
++ struct aufs_branch *br;
++ struct inode *h_dir;
++ char tgtname[PLINK_NAME_LEN];
++ int len;
++ struct lkup_args lkup;
++
++ LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
++ br = stobr(sb, bindex);
++ h_parent = br->br_plink;
++ DEBUG_ON(!h_parent);
++ h_dir = h_parent->d_inode;
++ DEBUG_ON(!h_dir);
++
++ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
++
++ // always superio.
++ lkup.nfsmnt = au_do_nfsmnt(br->br_mnt);
++ lkup.dlgt = need_dlgt(sb);
++ hi_lock_whplink(h_dir);
++ h_dentry = sio_lkup_one(tgtname, h_parent, len, &lkup);
++ i_unlock(h_dir);
++ return h_dentry;
++}
++
++static int do_whplink(char *tgt, int len, struct dentry *h_parent,
++ struct dentry *h_dentry, struct vfsmount *nfsmnt,
++ struct super_block *sb)
++{
++ int err;
++ struct dentry *h_tgt;
++ struct inode *h_dir;
++ struct lkup_args lkup = {
++ .nfsmnt = nfsmnt,
++ .dlgt = need_dlgt(sb)
++ };
++
++ h_tgt = lkup_one(tgt, h_parent, len, &lkup);
++ err = PTR_ERR(h_tgt);
++ if (IS_ERR(h_tgt))
++ goto out;
++
++ err = 0;
++ h_dir = h_parent->d_inode;
++ if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode))
++ err = vfsub_unlink(h_dir, h_tgt, lkup.dlgt);
++ if (!err && !h_tgt->d_inode) {
++ err = vfsub_link(h_dentry, h_dir, h_tgt, lkup.dlgt);
++ //inode->i_nlink++;
++ }
++ dput(h_tgt);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct do_whplink_args {
++ int *errp;
++ char *tgt;
++ int len;
++ struct dentry *h_parent;
++ struct dentry *h_dentry;
++ struct vfsmount *nfsmnt;
++ struct super_block *sb;
++};
++
++static void call_do_whplink(void *args)
++{
++ struct do_whplink_args *a = args;
++ *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
++ a->nfsmnt, a->sb);
++}
++
++static int whplink(struct dentry *h_dentry, struct inode *inode,
++ aufs_bindex_t bindex, struct super_block *sb)
++{
++ int err, len;
++ struct aufs_branch *br;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ char tgtname[PLINK_NAME_LEN];
++
++ LKTRTrace("%.*s\n", DLNPair(h_dentry));
++ br = stobr(inode->i_sb, bindex);
++ h_parent = br->br_plink;
++ DEBUG_ON(!h_parent);
++ h_dir = h_parent->d_inode;
++ DEBUG_ON(!h_dir);
++
++ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
++
++ // always superio.
++ hi_lock_whplink(h_dir);
++ if (!is_au_wkq(current)) {
++ struct do_whplink_args args = {
++ .errp = &err,
++ .tgt = tgtname,
++ .len = len,
++ .h_parent = h_parent,
++ .h_dentry = h_dentry,
++ .nfsmnt = au_do_nfsmnt(br->br_mnt),
++ .sb = sb
++ };
++ au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
++ } else
++ err = do_whplink(tgtname, len, h_parent, h_dentry,
++ au_do_nfsmnt(br->br_mnt), sb);
++ i_unlock(h_dir);
++
++ TraceErr(err);
++ return err;
++}
++
++void append_plink(struct super_block *sb, struct inode *inode,
++ struct dentry *h_dentry, aufs_bindex_t bindex)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++ int found, err, cnt;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++ SiMustAnyLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ cnt = 0;
++ found = 0;
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry(plink, plink_list, list) {
++ cnt++;
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ }
++
++ err = 0;
++ if (!found) {
++ struct pseudo_link *plink;
++
++ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
++ if (plink) {
++ plink->inode = igrab(inode);
++ list_add(&plink->list, plink_list);
++ cnt++;
++ } else
++ err = -ENOMEM;
++ }
++ spin_unlock(&sbinfo->si_plink_lock);
++
++ if (!err)
++ err = whplink(h_dentry, inode, bindex, sb);
++
++ if (unlikely(cnt > 100))
++ Warn1("unexpectedly many pseudo links, %d\n", cnt);
++ if (unlikely(err))
++ Warn("err %d, damaged pseudo link. ignored.\n", err);
++}
++
++static void do_put_plink(struct pseudo_link *plink, int do_del)
++{
++ TraceEnter();
++
++ iput(plink->inode);
++ if (do_del)
++ list_del(&plink->list);
++ kfree(plink);
++}
++
++void au_put_plink(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ //spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry_safe(plink, tmp, plink_list, list)
++ do_put_plink(plink, 0);
++ INIT_LIST_HEAD(plink_list);
++ //spin_unlock(&sbinfo->si_plink_lock);
++}
++
++void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id)
++{
++ struct aufs_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++ struct inode *inode;
++ aufs_bindex_t bstart, bend, bindex;
++ int do_put;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
++
++ sbinfo = stosi(sb);
++ plink_list = &sbinfo->si_plink;
++ //spin_lock(&sbinfo->si_plink_lock);
++ list_for_each_entry_safe(plink, tmp, plink_list, list) {
++ do_put = 0;
++ inode = igrab(plink->inode);
++ ii_write_lock_child(inode);
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (!au_h_iptr_i(inode, bindex)
++ || itoid_index(inode, bindex) != br_id)
++ continue;
++ set_h_iptr(inode, bindex, NULL, 0);
++ do_put = 1;
++ break;
++ }
++ } else
++ do_put_plink(plink, 1);
++
++ if (do_put) {
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (au_h_iptr_i(inode, bindex)) {
++ do_put = 0;
++ break;
++ }
++ if (do_put)
++ do_put_plink(plink, 1);
++ }
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++ //spin_unlock(&sbinfo->si_plink_lock);
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sbinfo.c linux-2.6.22.1/fs/aufs/sbinfo.c
+--- linux-2.6.22.1.oorig/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/sbinfo.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sbinfo.c,v 1.30 2007/05/14 03:39:31 sfjro Exp $ */
++
++#include "aufs.h"
++
++struct aufs_sbinfo *stosi(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++ sbinfo = sb->s_fs_info;
++ //DEBUG_ON(sbinfo->si_bend < 0);
++ return sbinfo;
++}
++
++aufs_bindex_t sbend(struct super_block *sb)
++{
++ SiMustAnyLock(sb);
++ return stosi(sb)->si_bend;
++}
++
++struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex)
++{
++ SiMustAnyLock(sb);
++ DEBUG_ON(bindex < 0 || sbend(sb) < bindex
++ || !stosi(sb)->si_branch[0 + bindex]);
++ return stosi(sb)->si_branch[0 + bindex];
++}
++
++int au_sigen(struct super_block *sb)
++{
++ SiMustAnyLock(sb);
++ return stosi(sb)->si_generation;
++}
++
++int au_sigen_inc(struct super_block *sb)
++{
++ int gen;
++
++ SiMustWriteLock(sb);
++ gen = ++stosi(sb)->si_generation;
++ au_update_digen(sb->s_root);
++ au_update_iigen(sb->s_root->d_inode);
++ sb->s_root->d_inode->i_version++;
++ return gen;
++}
++
++int find_bindex(struct super_block *sb, struct aufs_branch *br)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (stobr(sb, bindex) == br)
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry and super_block lock. call at entry point */
++void aufs_read_lock(struct dentry *dentry, int flags)
++{
++ si_read_lock(dentry->d_sb);
++ if (flags & AUFS_D_WLOCK)
++ di_write_lock_child(dentry);
++ else
++ di_read_lock_child(dentry, flags);
++}
++
++void aufs_read_unlock(struct dentry *dentry, int flags)
++{
++ if (flags & AUFS_D_WLOCK)
++ di_write_unlock(dentry);
++ else
++ di_read_unlock(dentry, flags);
++ si_read_unlock(dentry->d_sb);
++}
++
++void aufs_write_lock(struct dentry *dentry)
++{
++ //au_wkq_wait_nwtask();
++ si_write_lock(dentry->d_sb);
++ di_write_lock_child(dentry);
++}
++
++void aufs_write_unlock(struct dentry *dentry)
++{
++ di_write_unlock(dentry);
++ si_write_unlock(dentry->d_sb);
++ //au_wkq_wait_nwtask();
++}
++
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
++ si_read_lock(d1->d_sb);
++ di_write_lock2_child(d1, d2, isdir);
++}
++
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
++ di_write_unlock2(d1, d2);
++ si_read_unlock(d1->d_sb);
++}
++
++/* ---------------------------------------------------------------------- */
++
++aufs_bindex_t new_br_id(struct super_block *sb)
++{
++ aufs_bindex_t br_id;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++
++ while (1) {
++ br_id = ++stosi(sb)->si_last_br_id;
++ if (br_id && find_brindex(sb, br_id) < 0)
++ return br_id;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_SYSAUFS
++static int make_xino(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++ struct super_block *sb = args->sb;
++ aufs_bindex_t bindex, bend;
++ struct file *xf;
++ struct inode *xi;
++
++ TraceEnter();
++ DEBUG_ON(args->index != SysaufsSb_XINO);
++ SiMustReadLock(sb);
++
++ *do_size = 0;
++ err = seq_printf(seq, "%d %lu\n", sizeof(struct xino),
++ atomic_long_read(&stosi(sb)->si_xino));
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ xf = stobr(sb, bindex)->br_xino;
++ xi = xf->f_dentry->d_inode;
++ err = seq_printf(seq, "%d: %d, %Lux%d %Ld\n",
++ bindex, file_count(xf),
++ (u64)xi->i_blocks, 1 << xi->i_blkbits,
++ i_size_read(xi));
++ }
++ return err;
++}
++
++sysaufs_op au_si_ops[] = {
++ [SysaufsSb_XINO] = make_xino
++};
++#endif
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/super.c linux-2.6.22.1/fs/aufs/super.c
+--- linux-2.6.22.1.oorig/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/super.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,716 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: super.c,v 1.50 2007/05/14 03:39:42 sfjro Exp $ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/*
++ * super_operations
++ */
++static struct inode *aufs_alloc_inode(struct super_block *sb)
++{
++ struct aufs_icntnr *c;
++
++ TraceEnter();
++
++ c = cache_alloc_icntnr();
++ //if (LktrCond) {cache_free_icntnr(c); c = NULL;}
++ if (c) {
++ inode_init_once(&c->vfs_inode);
++ c->vfs_inode.i_version = 1; //sigen(sb);
++ c->iinfo.ii_hinode = NULL;
++ return &c->vfs_inode;
++ }
++ return NULL;
++}
++
++static void aufs_destroy_inode(struct inode *inode)
++{
++ LKTRTrace("i%lu\n", inode->i_ino);
++ au_iinfo_fin(inode);
++ cache_free_icntnr(container_of(inode, struct aufs_icntnr, vfs_inode));
++}
++
++//todo: how about merge with alloc_inode()?
++static void aufs_read_inode(struct inode *inode)
++{
++ int err;
++
++ LKTRTrace("i%lu\n", inode->i_ino);
++
++ err = au_iinfo_init(inode);
++ //if (LktrCond) err = -1;
++ if (!err) {
++ inode->i_version++;
++ inode->i_op = &aufs_iop;
++ inode->i_fop = &aufs_file_fop;
++ inode->i_mapping->a_ops = &aufs_aop;
++ return; /* success */
++ }
++
++ LKTRTrace("intializing inode info failed(%d)\n", err);
++ make_bad_inode(inode);
++}
++
++int au_show_brs(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ char a[16];
++ struct dentry *root;
++
++ TraceEnter();
++ SiMustAnyLock(sb);
++ root = sb->s_root;
++ DiMustAnyLock(root);
++
++ err = 0;
++ bend = sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ err = br_perm_str(a, sizeof(a), sbr_perm(sb, bindex));
++ if (!err)
++ err = seq_path(seq, sbr_mnt(sb, bindex),
++ au_h_dptr_i(root, bindex), au_esc_chars);
++ if (err > 0)
++ err = seq_printf(seq, "=%s", a);
++ if (!err && bindex != bend)
++ err = seq_putc(seq, ':');
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ int err, n;
++ struct super_block *sb;
++ struct aufs_sbinfo *sbinfo;
++ struct dentry *root;
++ struct file *xino;
++
++ TraceEnter();
++
++ sb = mnt->mnt_sb;
++ root = sb->s_root;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ if (au_flag_test(sb, AuFlag_XINO)) {
++ err = seq_puts(m, ",xino=");
++ if (unlikely(err))
++ goto out;
++ xino = stobr(sb, 0)->br_xino;
++ err = seq_path(m, xino->f_vfsmnt, xino->f_dentry, au_esc_chars);
++ if (unlikely(err <= 0))
++ goto out;
++ err = 0;
++
++#define Deleted "\\040(deleted)"
++ m->count -= sizeof(Deleted) - 1;
++ DEBUG_ON(memcmp(m->buf + m->count, Deleted,
++ sizeof(Deleted) - 1));
++#undef Deleted
++ } else
++ err = seq_puts(m, ",noxino");
++
++ n = au_flag_test(sb, AuFlag_PLINK);
++ if (unlikely(!err && (AuDefFlags & AuFlag_PLINK) != n))
++ err = seq_printf(m, ",%splink", n ? "" : "no");
++ n = au_flag_test_udba(sb);
++ if (unlikely(!err && (AuDefFlags & AuMask_UDBA) != n))
++ err = seq_printf(m, ",udba=%s", udba_str(n));
++ n = au_flag_test(sb, AuFlag_ALWAYS_DIROPQ);
++ if (unlikely(!err && (AuDefFlags & AuFlag_ALWAYS_DIROPQ) != n))
++ err = seq_printf(m, ",diropq=%c", n ? 'a' : 'w');
++ n = au_flag_test(sb, AuFlag_DLGT);
++ if (unlikely(!err && (AuDefFlags & AuFlag_DLGT) != n))
++ err = seq_printf(m, ",%sdlgt", n ? "" : "no");
++ n = au_flag_test(sb, AuFlag_WARN_PERM);
++ if (unlikely(!err && (AuDefFlags & AuFlag_WARN_PERM) != n))
++ err = seq_printf(m, ",%swarn_perm", n ? "" : "no");
++
++ sbinfo = stosi(sb);
++ n = sbinfo->si_dirwh;
++ if (unlikely(!err && n != AUFS_DIRWH_DEF))
++ err = seq_printf(m, ",dirwh=%d", n);
++ n = sbinfo->si_rdcache / HZ;
++ if (unlikely(!err && n != AUFS_RDCACHE_DEF))
++ err = seq_printf(m, ",rdcache=%d", n);
++#if 0
++ n = au_flag_test_coo(sb);
++ if (unlikely(!err && (AuDefFlags & AuMask_COO) != n))
++ err = seq_printf(m, ",coo=%s", coo_str(n));
++#endif
++
++ if (!err && !sysaufs_brs) {
++#ifdef CONFIG_AUFS_COMPAT
++ err = seq_puts(m, ",dirs=");
++#else
++ err = seq_puts(m, ",br:");
++#endif
++ if (!err)
++ err = au_show_brs(m, sb);
++ }
++
++ out:
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ TraceErr(err);
++ if (err)
++ err = -E2BIG;
++ TraceErr(err);
++ return err;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#define StatfsLock(d) aufs_read_lock((d)->d_sb->s_root, 0)
++#define StatfsUnlock(d) aufs_read_unlock((d)->d_sb->s_root, 0)
++#define StatfsArg(d) au_h_dptr((d)->d_sb->s_root)
++#define StatfsHInode(d) (StatfsArg(d)->d_inode)
++#define StatfsSb(d) ((d)->d_sb)
++static int aufs_statfs(struct dentry *arg, struct kstatfs *buf)
++#else
++#define StatfsLock(s) si_read_lock(s)
++#define StatfsUnlock(s) si_read_unlock(s)
++#define StatfsArg(s) sbr_sb(s, 0)
++#define StatfsHInode(s) (StatfsArg(s)->s_root->d_inode)
++#define StatfsSb(s) (s)
++static int aufs_statfs(struct super_block *arg, struct kstatfs *buf)
++#endif
++{
++ int err;
++
++ TraceEnter();
++
++ StatfsLock(arg);
++ err = vfsub_statfs(StatfsArg(arg), buf, need_dlgt(StatfsSb(arg)));
++ //if (LktrCond) err = -1;
++ StatfsUnlock(arg);
++ if (!err) {
++ //buf->f_type = AUFS_SUPER_MAGIC;
++ buf->f_type = 0;
++ buf->f_namelen -= AUFS_WH_PFX_LEN;
++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
++ }
++ //buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
++
++ TraceErr(err);
++ return err;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) || defined(UbuntuEdgy17Umount18)
++#define UmountBeginSb(mnt) (mnt)->mnt_sb
++static void aufs_umount_begin(struct vfsmount *arg, int flags)
++#else
++#define UmountBeginSb(sb) sb
++static void aufs_umount_begin(struct super_block *arg)
++#endif
++{
++ struct super_block *sb = UmountBeginSb(arg);
++
++ if (unlikely(!stosi(sb)))
++ return;
++
++ //au_wkq_wait_nwtask();
++ si_write_lock(sb);
++ if (au_flag_test(sb, AuFlag_PLINK)) {
++ au_put_plink(sb);
++ //kobj_umount(stosi(sb));
++ }
++#if 0
++ if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
++ shrink_dcache_sb(sb);
++#endif
++ si_write_unlock(sb);
++}
++
++static void free_sbinfo(struct aufs_sbinfo *sbinfo)
++{
++ TraceEnter();
++ DEBUG_ON(!sbinfo
++ || !list_empty(&sbinfo->si_plink));
++
++ free_branches(sbinfo);
++ kfree(sbinfo->si_branch);
++ kfree(sbinfo);
++}
++
++/* final actions when unmounting a file system */
++static void aufs_put_super(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++
++ sbinfo = stosi(sb);
++ if (unlikely(!sbinfo))
++ return;
++
++ sysaufs_del(sbinfo);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(UbuntuEdgy17Umount18)
++ // umount_begin() may not be called.
++ aufs_umount_begin(sb);
++#endif
++ free_sbinfo(sbinfo);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * refresh directories at remount time.
++ */
++static int do_refresh_dir(struct dentry *dentry, unsigned int flags)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *inode;
++
++ LKTRTrace("%.*s\n", DLNPair(dentry));
++ inode = dentry->d_inode;
++ DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
++
++ di_write_lock_child(dentry);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AUFS_I_RLOCK);
++ err = au_refresh_hdentry(dentry, S_IFDIR);
++ if (err >= 0) {
++ err = au_refresh_hinode(inode, dentry);
++ if (!err)
++ au_reset_hinotify(inode, flags);
++ }
++ if (unlikely(err))
++ Err("unrecoverable error %d\n", err);
++ di_read_unlock(parent, AUFS_I_RLOCK);
++ dput(parent);
++ di_write_unlock(dentry);
++
++ TraceErr(err);
++ return err;
++}
++
++static int test_dir(struct dentry *dentry, void *arg)
++{
++ return S_ISDIR(dentry->d_inode->i_mode);
++}
++
++static int refresh_dir(struct dentry *root, int sgen)
++{
++ int err, i, j, ndentry;
++ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ LKTRTrace("sgen %d\n", sgen);
++ SiMustWriteLock(root->d_sb);
++ DEBUG_ON(au_digen(root) != sgen);
++ DiMustWriteLock(root);
++
++ err = au_dpages_init(&dpages, GFP_KERNEL);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, test_dir, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; !err && j < ndentry; j++) {
++ struct dentry *d;
++ d = dentries[j];
++ DEBUG_ON(!S_ISDIR(d->d_inode->i_mode)
++ || IS_ROOT(d)
++ || au_digen(d->d_parent) != sgen);
++ if (au_digen(d) != sgen)
++ err = do_refresh_dir(d, flags);
++ }
++ }
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++ TraceErr(err);
++
++ switch (err) {
++ case -ENOENT:
++ case -ENOTDIR:
++ case -EEXIST:
++ case -EIO:
++ err = -EINVAL;
++ }
++ return err;
++}
++
++/* protected by s_umount */
++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++ int err, do_refresh;
++ struct dentry *root;
++ struct inode *inode;
++ struct opts opts;
++ unsigned int given, dlgt;
++
++ //au_debug_on();
++ LKTRTrace("flags 0x%x, data %s, len %d\n",
++ *flags, data ? data : "NULL", data ? strlen(data) : 0);
++
++ err = 0;
++ if (unlikely(!data || !*data))
++ goto out; /* success */
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void*)__get_free_page(GFP_KERNEL);
++ //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++
++ /* parse it before aufs lock */
++ err = au_parse_opts(sb, data, &opts);
++ //if (LktrCond) {au_free_opts(&opts); err = -1;}
++ if (unlikely(err))
++ goto out_opts;
++
++ root = sb->s_root;
++ inode = root->d_inode;
++ i_lock(inode);
++ aufs_write_lock(root);
++
++ //DbgSleep(3);
++
++ /* au_do_opts() may return an error */
++ do_refresh = 0;
++ given = 0;
++ err = au_do_opts_remount(sb, &opts, &do_refresh, &given);
++ //if (LktrCond) err = -1;
++ au_free_opts(&opts);
++
++ if (do_refresh) {
++ int rerr;
++ struct aufs_sbinfo *sbinfo;
++
++ dlgt = au_flag_test(sb, AuFlag_DLGT);
++ au_flag_clr(sb, AuFlag_DLGT);
++ au_sigen_inc(sb);
++ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++ sbinfo = stosi(sb);
++ sbinfo->si_failed_refresh_dirs = 0;
++ rerr = refresh_dir(root, au_sigen(sb));
++ if (unlikely(rerr)) {
++ sbinfo->si_failed_refresh_dirs = 1;
++ Warn("Refreshing directories failed, ignores (%d)\n",
++ rerr);
++ }
++ au_cpup_attr_all(inode);
++ au_flag_set(sb, dlgt);
++ }
++
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ /* braces are added to stop a warning */
++ if (do_refresh) {
++ sysaufs_notify_remount();
++ }
++
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ err = cvt_err(err);
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++static struct super_operations aufs_sop = {
++ .alloc_inode = aufs_alloc_inode,
++ .destroy_inode = aufs_destroy_inode,
++ .read_inode = aufs_read_inode,
++ //.dirty_inode = aufs_dirty_inode,
++ //.write_inode = aufs_write_inode,
++ //void (*put_inode) (struct inode *);
++ .drop_inode = generic_delete_inode,
++ //.delete_inode = aufs_delete_inode,
++ //.clear_inode = aufs_clear_inode,
++
++ .show_options = aufs_show_options,
++ .statfs = aufs_statfs,
++
++ .put_super = aufs_put_super,
++ //void (*write_super) (struct super_block *);
++ //int (*sync_fs)(struct super_block *sb, int wait);
++ //void (*write_super_lockfs) (struct super_block *);
++ //void (*unlockfs) (struct super_block *);
++ .remount_fs = aufs_remount_fs,
++ // depends upon umount flags. also use put_super() (< 2.6.18)
++ .umount_begin = aufs_umount_begin
++};
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * at first mount time.
++ */
++
++static int alloc_sbinfo(struct super_block *sb)
++{
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++
++ sbinfo = kmalloc(sizeof(*sbinfo), GFP_KERNEL);
++ //if (LktrCond) {kfree(sbinfo); sbinfo = NULL;}
++ if (unlikely(!sbinfo))
++ goto out;
++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_KERNEL);
++ //if (LktrCond) {kfree(sbinfo->si_branch); sbinfo->si_branch = NULL;}
++ if (unlikely(!sbinfo->si_branch)) {
++ kfree(sbinfo);
++ goto out;
++ }
++ rw_init_wlock(&sbinfo->si_rwsem);
++ sbinfo->si_bend = -1;
++ atomic_long_set(&sbinfo->si_xino, AUFS_FIRST_INO);
++ spin_lock_init(&sbinfo->si_plink_lock);
++ INIT_LIST_HEAD(&sbinfo->si_plink);
++ init_lvma(sbinfo);
++ sbinfo->si_generation = 0;
++ sbinfo->si_last_br_id = 0;
++ sbinfo->si_failed_refresh_dirs = 0;
++ sbinfo->si_flags = 0;
++ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
++ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++ //atomic_set(&sbinfo->si_hinotify, 0);
++ //init_waitqueue_head(&sbinfo->si_hinotify_wq);
++
++ sb->s_fs_info = sbinfo;
++ au_flag_set(sb, AuDefFlags);
++#ifdef ForceInotify
++ udba_set(sb, AuFlag_UDBA_INOTIFY);
++#endif
++#ifdef ForceDlgt
++ au_flag_set(sb, AuFlag_DLGT);
++#endif
++#ifdef ForceNoPlink
++ au_flag_clr(sb, AuFlag_PLINK);
++#endif
++ return 0; /* success */
++
++ out:
++ TraceErr(-ENOMEM);
++ return -ENOMEM;
++}
++
++static int alloc_root(struct super_block *sb)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *root;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ inode = iget(sb, AUFS_ROOT_INO);
++ //if (LktrCond) {iput(inode); inode = NULL;}
++ if (unlikely(!inode))
++ goto out;
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++ err = -ENOMEM;
++ if (unlikely(is_bad_inode(inode)))
++ goto out_iput;
++
++ root = d_alloc_root(inode);
++ //if (LktrCond) {igrab(inode); dput(root); root = NULL;}
++ if (unlikely(!root))
++ goto out_iput;
++ err = PTR_ERR(root);
++ if (IS_ERR(root))
++ goto out_iput;
++
++ err = au_alloc_dinfo(root);
++ //if (LktrCond){rw_write_unlock(&dtodi(root)->di_rwsem);err=-1;}
++ if (!err) {
++ sb->s_root = root;
++ return 0; /* success */
++ }
++ dput(root);
++ goto out; /* do not iput */
++
++ out_iput:
++ iput(inode);
++ out:
++ TraceErr(err);
++ return err;
++
++}
++
++static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
++{
++ int err;
++ struct dentry *root;
++ struct inode *inode;
++ struct opts opts;
++ char *arg = raw_data;
++
++ //au_debug_on();
++ if (unlikely(!arg || !*arg)) {
++ err = -EINVAL;
++ Err("no arg\n");
++ goto out;
++ }
++ LKTRTrace("%s, silent %d\n", arg, silent);
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void*)__get_free_page(GFP_KERNEL);
++ //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++
++ err = alloc_sbinfo(sb);
++ //if (LktrCond) {si_write_unlock(sb);free_sbinfo(stosi(sb));err=-1;}
++ if (unlikely(err))
++ goto out_opts;
++ SiMustWriteLock(sb);
++ /* all timestamps always follow the ones on the branch */
++ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
++ sb->s_op = &aufs_sop;
++ au_init_export_op(sb);
++ //err = kobj_mount(stosi(sb));
++ //if (err)
++ //goto out_info;
++
++ err = alloc_root(sb);
++ //if (LktrCond) {rw_write_unlock(&dtodi(sb->s_root)->di_rwsem);
++ //dput(sb->s_root);sb->s_root=NULL;err=-1;}
++ if (unlikely(err)) {
++ DEBUG_ON(sb->s_root);
++ si_write_unlock(sb);
++ goto out_info;
++ }
++ root = sb->s_root;
++ DiMustWriteLock(root);
++ inode = root->d_inode;
++ inode->i_nlink = 2;
++
++ /*
++ * actually we can parse options regardless aufs lock here.
++ * but at remount time, parsing must be done before aufs lock.
++ * so we follow the same rule.
++ */
++ ii_write_lock_parent(inode);
++ aufs_write_unlock(root);
++ err = au_parse_opts(sb, arg, &opts);
++ //if (LktrCond) {au_free_opts(&opts); err = -1;}
++ if (unlikely(err))
++ goto out_root;
++
++ /* lock vfs_inode first, then aufs. */
++ i_lock(inode);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ aufs_write_lock(root);
++
++ sb->s_maxbytes = 0;
++ err = au_do_opts_mount(sb, &opts);
++ //if (LktrCond) err = -1;
++ au_free_opts(&opts);
++ if (unlikely(err))
++ goto out_unlock;
++ DEBUG_ON(!sb->s_maxbytes);
++
++ //DbgDentry(root);
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ //DbgSb(sb);
++ goto out_opts; /* success */
++
++ out_unlock:
++ aufs_write_unlock(root);
++ i_unlock(inode);
++ out_root:
++ dput(root);
++ sb->s_root = NULL;
++ out_info:
++ free_sbinfo(stosi(sb));
++ sb->s_fs_info = NULL;
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ TraceErr(err);
++ err = cvt_err(err);
++ TraceErr(err);
++ //au_debug_off();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++static int aufs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *raw_data,
++ struct vfsmount *mnt)
++{
++ int err;
++
++ /* all timestamps always follow the ones on the branch */
++ //mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME;
++ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
++ if (!err) {
++ struct aufs_sbinfo *sbinfo = stosi(mnt->mnt_sb);
++ sbinfo->si_mnt = mnt;
++ sysaufs_add(sbinfo);
++ }
++ return err;
++}
++#else
++static struct super_block *aufs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name,
++ void *raw_data)
++{
++ return get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super);
++}
++#endif
++
++struct file_system_type aufs_fs_type = {
++ .name = AUFS_FSTYPE,
++ .fs_flags = FS_REVAL_DOT, // for UDBA and NFS branch
++ .get_sb = aufs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ //no need to __module_get() and module_put().
++ .owner = THIS_MODULE,
++};
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/super.h linux-2.6.22.1/fs/aufs/super.h
+--- linux-2.6.22.1.oorig/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/super.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,339 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: super.h,v 1.44 2007/05/14 03:39:54 sfjro Exp $ */
++
++#ifndef __AUFS_SUPER_H__
++#define __AUFS_SUPER_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/version.h>
++#include <linux/aufs_type.h>
++#include "misc.h"
++#include "sysaufs.h"
++
++#ifdef CONFIG_AUFS_SYSAUFS
++/* entries under sysfs per mount-point */
++enum {SysaufsSb_XINO, /* SysaufsSb_PLINK, */ SysaufsSb_Last};
++struct sysaufs_sbinfo {
++ au_subsys_t subsys;
++ struct sysaufs_entry array[SysaufsSb_Last];
++};
++extern sysaufs_op au_si_ops[];
++#else
++struct sysaufs_sbinfo {};
++#endif
++
++struct aufs_sbinfo {
++ struct aufs_rwsem si_rwsem;
++
++ /* branch management */
++ /* wrap around attack by superuser? No. */
++ int si_generation;
++
++ /*
++ * set true when refresh_dirs() at remount time failed.
++ * then try refreshing dirs at access time again.
++ * if it is false, refreshing dirs at access time is unnecesary
++ */
++ unsigned int si_failed_refresh_dirs:1;
++
++ aufs_bindex_t si_bend;
++ aufs_bindex_t si_last_br_id;
++ struct aufs_branch **si_branch;
++
++ /* mount flags */
++ unsigned int si_flags;
++
++ /* external inode number table */
++ atomic_long_t si_xino; // time bomb
++ //struct file *si_xino_bmap;
++
++ /* readdir cache time, max, in HZ */
++ unsigned long si_rdcache;
++
++ /*
++ * If the number of whiteouts are larger than si_dirwh, leave all of
++ * them after rename_whtmp to reduce the cost of rmdir(2).
++ * future fsck.aufs or kernel thread will remove them later.
++ * Otherwise, remove all whiteouts and the dir in rmdir(2).
++ */
++ unsigned int si_dirwh;
++
++ /* pseudo_link list */ // dirty
++ spinlock_t si_plink_lock;
++ struct list_head si_plink;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++ /* super_blocks list is not exported */
++ struct list_head si_list;
++ struct vfsmount *si_mnt; /* no get/put */
++#endif
++
++ /* sysfs */
++ struct sysaufs_sbinfo si_sysaufs;
++
++#ifdef CONFIG_AUFS_HINOTIFY
++ /* hinotify */
++ //atomic_t si_hinotify;
++ //wait_queue_head_t si_hinotify_wq;
++#endif
++
++#ifdef CONFIG_AUFS_ROBR
++ /* locked vma list for mmap() */ // very dirty
++ spinlock_t si_lvma_lock;
++ struct list_head si_lvma;
++#endif
++};
++
++/* an entry in a xino file */
++struct xino {
++ ino_t ino;
++ //__u32 h_gen;
++} __attribute__ ((packed));
++
++//#define AuXino_INVALID_HGEN (-1)
++
++/* ---------------------------------------------------------------------- */
++
++/* Mount flags */
++#define AuFlag_XINO 1
++#define AuFlag_ZXINO (1 << 1)
++#define AuFlag_PLINK (1 << 2)
++#define AuFlag_UDBA_NONE (1 << 3)
++#define AuFlag_UDBA_REVAL (1 << 4)
++#define AuFlag_UDBA_INOTIFY (1 << 5)
++#define AuFlag_WARN_PERM (1 << 6)
++#define AuFlag_COO_NONE (1 << 7)
++#define AuFlag_COO_LEAF (1 << 8)
++#define AuFlag_COO_ALL (1 << 9)
++#define AuFlag_ALWAYS_DIROPQ (1 << 10)
++#define AuFlag_DLGT (1 << 11)
++
++#define AuMask_UDBA (AuFlag_UDBA_NONE | AuFlag_UDBA_REVAL \
++ | AuFlag_UDBA_INOTIFY)
++#define AuMask_COO (AuFlag_COO_NONE | AuFlag_COO_LEAF \
++ | AuFlag_COO_ALL)
++
++#ifdef CONFIG_AUFS_COMPAT
++#define AuDefFlag_DIROPQ AuFlag_ALWAYS_DIROPQ
++#else
++#define AuDefFlag_DIROPQ 0
++#endif
++
++#define AuDefFlags_COMM (AuFlag_XINO | AuFlag_UDBA_REVAL | AuFlag_WARN_PERM \
++ | AuFlag_COO_NONE | AuDefFlag_DIROPQ)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#define AuDefFlags (AuDefFlags_COMM | AuFlag_PLINK)
++#else
++#define AuDefFlags AuDefFlags_COMM
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* flags for aufs_read_lock()/di_read_lock() */
++#define AUFS_D_WLOCK 1
++#define AUFS_I_RLOCK 2
++#define AUFS_I_WLOCK 4
++
++/* ---------------------------------------------------------------------- */
++
++/* super.c */
++int au_show_brs(struct seq_file *seq, struct super_block *sb);
++
++/* xino.c */
++struct file *xino_create(struct super_block *sb, char *fname, int silent,
++ struct dentry *parent);
++ino_t xino_new_ino(struct super_block *sb);
++int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino);
++int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino);
++int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino);
++int xino_init(struct super_block *sb, aufs_bindex_t bindex,
++ struct file *base_file, int do_test);
++struct opt_xino;
++int xino_set(struct super_block *sb, struct opt_xino *xino, int remount);
++int xino_clr(struct super_block *sb);
++struct file *xino_def(struct super_block *sb);
++
++/* sbinfo.c */
++struct aufs_sbinfo *stosi(struct super_block *sb);
++aufs_bindex_t sbend(struct super_block *sb);
++struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex);
++int au_sigen(struct super_block *sb);
++int au_sigen_inc(struct super_block *sb);
++int find_bindex(struct super_block *sb, struct aufs_branch *br);
++
++void aufs_read_lock(struct dentry *dentry, int flags);
++void aufs_read_unlock(struct dentry *dentry, int flags);
++void aufs_write_lock(struct dentry *dentry);
++void aufs_write_unlock(struct dentry *dentry);
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++aufs_bindex_t new_br_id(struct super_block *sb);
++
++/* ---------------------------------------------------------------------- */
++
++static inline const char *au_sbtype(struct super_block *sb)
++{
++ return sb->s_type->name;
++}
++
++static inline int au_is_aufs(struct super_block *sb)
++{
++ return !strcmp(au_sbtype(sb), AUFS_FSTYPE);
++}
++
++static inline int au_is_nfs(struct super_block *sb)
++{
++#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "nfs");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_is_remote(struct super_block *sb)
++{
++ return au_is_nfs(sb);
++}
++
++#ifdef CONFIG_AUFS_EXPORT
++static inline void au_init_export_op(struct super_block *sb)
++{
++ extern struct export_operations aufs_export_op;
++ sb->s_export_op = &aufs_export_op;
++}
++
++static inline int au_is_nfsd(struct task_struct *tsk)
++{
++ return (!tsk->mm && !strcmp(tsk->comm, "nfsd"));
++}
++
++static inline void au_nfsd_lockdep_off(void)
++{
++ /* braces are added to stop a warning */
++ if (au_is_nfsd(current)) {
++ lockdep_off();
++ }
++}
++
++static inline void au_nfsd_lockdep_on(void)
++{
++ /* braces are added to stop a warning */
++ if (au_is_nfsd(current)) {
++ lockdep_on();
++ }
++}
++#else
++static inline int au_is_nfsd(struct task_struct *tsk)
++{
++ return 0;
++}
++static inline void au_init_export_op(struct super_block *sb)
++{
++ /* nothing */
++}
++#define au_nfsd_lockdep_off() /* */
++#define au_nfsd_lockdep_on() /* */
++#endif /* CONFIG_AUFS_EXPORT */
++
++static inline void init_lvma(struct aufs_sbinfo *sbinfo)
++{
++#ifdef CONFIG_AUFS_ROBR
++ spin_lock_init(&sbinfo->si_lvma_lock);
++ INIT_LIST_HEAD(&sbinfo->si_lvma);
++#else
++ /* nothing */
++#endif
++}
++
++/* limited support before 2.6.18 */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++static inline void au_mntget(struct super_block *sb)
++{
++ mntget(stosi(sb)->si_mnt);
++}
++
++static inline void au_mntput(struct super_block *sb)
++{
++ mntput(stosi(sb)->si_mnt);
++}
++#else
++static inline void au_mntget(struct super_block *sb)
++{
++ /* empty */
++}
++
++static inline void au_mntput(struct super_block *sb)
++{
++ /* empty */
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static inline void au_flag_set(struct super_block *sb, unsigned int flag)
++{
++ //SiMustWriteLock(sb);
++ stosi(sb)->si_flags |= flag;
++}
++
++static inline void au_flag_clr(struct super_block *sb, unsigned int flag)
++{
++ //SiMustWriteLock(sb);
++ stosi(sb)->si_flags &= ~flag;
++}
++
++static inline
++unsigned int au_flag_test(struct super_block *sb, unsigned int flag)
++{
++ //SiMustAnyLock(sb);
++ return stosi(sb)->si_flags & flag;
++}
++
++static inline unsigned int au_flag_test_udba(struct super_block *sb)
++{
++ return au_flag_test(sb, AuMask_UDBA);
++}
++
++static inline unsigned int au_flag_test_coo(struct super_block *sb)
++{
++ return au_flag_test(sb, AuMask_COO);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock superblock. mainly for entry point functions */
++/*
++ * si_read_lock, si_write_lock,
++ * si_read_unlock, si_write_unlock, si_downgrade_lock
++ */
++SimpleRwsemFuncs(si, struct super_block *sb, stosi(sb)->si_rwsem);
++
++/* to debug easier, do not make them inlined functions */
++#define SiMustReadLock(sb) RwMustReadLock(&stosi(sb)->si_rwsem)
++#define SiMustWriteLock(sb) RwMustWriteLock(&stosi(sb)->si_rwsem)
++#define SiMustAnyLock(sb) RwMustAnyLock(&stosi(sb)->si_rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SUPER_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sysaufs.c linux-2.6.22.1/fs/aufs/sysaufs.c
+--- linux-2.6.22.1.oorig/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/sysaufs.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,620 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sysaufs.c,v 1.6 2007/05/14 03:40:10 sfjro Exp $ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* super_blocks list is not exported */
++static DEFINE_MUTEX(aufs_sbilist_mtx);
++static LIST_HEAD(aufs_sbilist);
++
++/* ---------------------------------------------------------------------- */
++
++typedef ssize_t (*rwfunc_t)(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args);
++static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args);
++static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf, loff_t
++ offset, size_t sz, struct sysaufs_args *args);
++
++#define GFunc(name, _index, func) \
++static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
++{ \
++ struct sysaufs_args args = { \
++ .index = (_index), \
++ .mtx = &aufs_sbilist_mtx, \
++ .sb = NULL \
++ }; \
++ return func(kobj, buf, offset, sz, &args); \
++}
++
++#define GFuncs(name, _index) \
++ GFunc(read_##name, _index, sysaufs_read); \
++ GFunc(write_##name, _index, sysaufs_free_write);
++
++static struct super_block *find_sb_locked(struct kobject *kobj)
++{
++ struct super_block *sb;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ sb = NULL;
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ if (&au_subsys_to_kset(sbinfo->si_sysaufs.subsys).kobj != kobj)
++ continue;
++ sb = sbinfo->si_mnt->mnt_sb;
++ si_read_lock(sb);
++ break;
++ }
++ return sb;
++}
++
++static ssize_t sb_func(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args, rwfunc_t func)
++{
++ ssize_t err;
++
++ err = -ENOENT;
++ mutex_lock(&aufs_sbilist_mtx);
++ args->sb = find_sb_locked(kobj);
++ if (args->sb) {
++ err = func(kobj, buf, offset, sz, args);
++ si_read_unlock(args->sb);
++ }
++ mutex_unlock(&aufs_sbilist_mtx);
++ return err;
++}
++
++#define SbFunc(name, _index, func) \
++static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
++{ \
++ struct sysaufs_args args = { \
++ .index = (_index), \
++ .mtx = NULL \
++ }; \
++ return sb_func(kobj, buf, offset, sz, &args, func); \
++}
++
++#define SbFuncs(name, index) \
++ SbFunc(read_##name, index, sysaufs_read); \
++ SbFunc(write_##name, index, sysaufs_free_write)
++
++static decl_subsys(aufs, NULL, NULL);
++enum {Brs, Stat, Config, _Last};
++static struct sysaufs_entry g_array[_Last];
++GFuncs(brs, Brs);
++GFuncs(stat, Stat);
++GFuncs(config, Config);
++
++SbFuncs(xino, SysaufsSb_XINO);
++
++#define SetEntry(e, _name, init_size, _ops) \
++ do { \
++ (e)->attr.attr.name = #_name; \
++ (e)->attr.attr.owner = THIS_MODULE; \
++ (e)->attr.attr.mode = S_IRUGO | S_IWUSR; \
++ (e)->attr.read = read_##_name; \
++ (e)->attr.write = write_##_name; \
++ (e)->allocated = init_size; \
++ (e)->err = -1; \
++ (e)->ops = _ops; \
++ } while (0)
++
++#define Priv(e) (e)->attr.private
++#define Allocated(e) (e)->allocated
++#define Len(e) (e)->attr.size
++#define Name(e) attr_name((e)->attr)
++
++/* ---------------------------------------------------------------------- */
++
++static void free_entry(struct sysaufs_entry *e)
++{
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(!Priv(e));
++
++ if (Allocated(e) > 0)
++ kfree(Priv(e));
++ else
++ free_pages((unsigned long)Priv(e), -Allocated(e));
++ Priv(e) = NULL;
++ Len(e) = 0;
++}
++
++static void free_entries(void)
++{
++ static int a[] = {Brs, -1};
++ int *p = a;
++
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ while (*p >= 0) {
++ if (Priv(g_array + *p))
++ free_entry(g_array + *p);
++ p++;
++ }
++}
++
++static int alloc_entry(struct sysaufs_entry *e)
++{
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(Priv(e));
++ //Dbg("%d\n", Allocated(e));
++
++ if (Allocated(e) > 0)
++ Priv(e) = kmalloc(Allocated(e), GFP_KERNEL);
++ else
++ Priv(e) = (void*)__get_free_pages(GFP_KERNEL, -Allocated(e));
++ if (Priv(e))
++ return 0;
++ return -ENOMEM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void unreg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
++ au_subsys_t *parent)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < n; i++, a++)
++ if (!a->err) {
++ sysfs_remove_bin_file
++ (&au_subsys_to_kset(*subsys).kobj, &a->attr);
++ if (Priv(a))
++ free_entry(a);
++ }
++
++ subsystem_unregister(subsys);
++ subsys_put(parent);
++}
++
++static int reg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
++ au_subsys_t *parent)
++{
++ int err, i;
++
++ TraceEnter();
++
++ subsys_get(parent);
++ kobj_set_kset_s(&au_subsys_to_kset(*subsys), *parent);
++ err = subsystem_register(subsys);
++ if (unlikely(err))
++ goto out;
++
++ for (i = 0; !err && i < n; i++)
++ err = a[i].err = sysfs_create_bin_file
++ (&au_subsys_to_kset(*subsys).kobj, &a[i].attr);
++ if (unlikely(err))
++ unreg(subsys, a, n, parent);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define SbSetEntry(index, name, init_size) \
++ SetEntry(sa->array + index, name, init_size, au_si_ops);
++
++void sysaufs_add(struct aufs_sbinfo *sbinfo)
++{
++ int err;
++ struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
++
++ TraceEnter();
++
++ mutex_lock(&aufs_sbilist_mtx);
++ list_add_tail(&sbinfo->si_list, &aufs_sbilist);
++ free_entries();
++
++ memset(sa, 0, sizeof(*sa));
++ SbSetEntry(SysaufsSb_XINO, xino, 128);
++ err = kobject_set_name(&au_subsys_to_kset(sa->subsys).kobj, "%p",
++ sbinfo->si_mnt->mnt_sb);
++ if (!err)
++ err = reg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array),
++ &aufs_subsys);
++ if (unlikely(err))
++ Warn("failed adding sysfs (%d)\n", err);
++
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++void sysaufs_del(struct aufs_sbinfo *sbinfo)
++{
++ struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
++
++ TraceEnter();
++
++ mutex_lock(&aufs_sbilist_mtx);
++ unreg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array), &aufs_subsys);
++ list_del(&sbinfo->si_list);
++ free_entries();
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++void sysaufs_notify_remount(void)
++{
++ mutex_lock(&aufs_sbilist_mtx);
++ free_entries();
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int make_brs(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++ struct aufs_sbinfo *sbinfo;
++
++ TraceEnter();
++ MtxMustLock(&aufs_sbilist_mtx);
++ DEBUG_ON(args->index != Brs);
++
++ err = 0;
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ struct super_block *sb;
++ struct dentry *root;
++ struct vfsmount *mnt;
++
++ sb = sbinfo->si_mnt->mnt_sb;
++ root = sb->s_root;
++ aufs_read_lock(root, !AUFS_I_RLOCK);
++ mnt = sbinfo->si_mnt;
++ err = seq_escape
++ (seq, mnt->mnt_devname ? mnt->mnt_devname : "none",
++ au_esc_chars);
++ if (!err)
++ err = seq_putc(seq, ' ');
++ if (!err)
++ err = seq_path(seq, mnt, root, au_esc_chars);
++ if (err > 0)
++ err = seq_printf(seq, " %p br:", sb);
++ if (!err)
++ err = au_show_brs(seq, sb);
++ aufs_read_unlock(root, !AUFS_I_RLOCK);
++ if (!err)
++ err = seq_putc(seq, '\n');
++ else
++ break;
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++static int make_config(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err;
++
++ TraceEnter();
++ DEBUG_ON(args->index != Config);
++
++#ifdef CONFIG_AUFS
++ err = seq_puts(seq, "CONFIG_AUFS=y\n");
++#else
++ err = seq_puts(seq, "CONFIG_AUFS=m\n");
++#endif
++
++#define puts(m, v) \
++ if (!err) err = seq_puts(seq, "CONFIG_AUFS_" #m "=" #v "\n")
++#define puts_bool(m) puts(m, y)
++#define puts_mod(m) puts(m, m)
++
++#ifdef CONFIG_AUFS_FAKE_DM
++ puts_bool(FAKE_DM);
++#endif
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++ puts_bool(BRANCH_MAX_127);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
++ puts_bool(BRANCH_MAX_511);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++ puts_bool(BRANCH_MAX_1023);
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++ puts_bool(BRANCH_MAX_32767);
++#endif
++ puts_bool(SYSAUFS);
++#ifdef CONFIG_AUFS_HINOTIFY
++ puts_bool(HINOTIFY);
++#endif
++#ifdef CONFIG_AUFS_EXPORT
++ puts_bool(EXPORT);
++#endif
++#ifdef CONFIG_AUFS_ROBR
++ puts_bool(ROBR);
++#endif
++#ifdef CONFIG_AUFS_DLGT
++ puts_bool(DLGT);
++#endif
++#ifdef CONFIG_AUFS_LHASH_PATCH
++ puts_bool(LHASH_PATCH);
++#endif
++#ifdef CONFIG_AUFS_KSIZE_PATCH
++ puts_bool(KSIZE_PATCH);
++#endif
++#ifdef CONFIG_AUFS_DEBUG
++ puts_bool(DEBUG);
++#endif
++#ifdef CONFIG_AUFS_COMPAT
++ puts_bool(COMPAT);
++#endif
++
++#undef puts_bool
++#undef puts
++
++ TraceErr(err);
++ return err;
++}
++
++static int make_stat(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size)
++{
++ int err, i;
++
++ TraceEnter();
++ DEBUG_ON(args->index != Stat);
++
++ *do_size = 0;
++ err = seq_puts(seq, "wkq max_busy:");
++ for (i = 0; !err && i < aufs_nwkq; i++)
++ err = seq_printf(seq, " %u", au_wkq[i].max_busy);
++ if (!err)
++ err = seq_printf(seq, ", %u(generic)\n",
++ au_wkq[aufs_nwkq].max_busy);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int make(struct sysaufs_entry *e, struct sysaufs_args *args,
++ int *do_size)
++
++{
++ int err;
++ struct seq_file *seq;
++
++ TraceEnter();
++ DEBUG_ON(Priv(e));
++ MtxMustLock(&aufs_sbilist_mtx);
++
++ err = -ENOMEM;
++ seq = kzalloc(sizeof(*seq), GFP_KERNEL);
++ if (unlikely(!seq))
++ goto out;
++
++ Len(e) = 0;
++ while (1) {
++ err = alloc_entry(e);
++ if (unlikely(err))
++ break;
++
++ //mutex_init(&seq.lock);
++ seq->buf = Priv(e);
++ seq->count = 0;
++ seq->size = Allocated(e);
++ if (unlikely(Allocated(e) <= 0))
++ seq->size = PAGE_SIZE << -Allocated(e);
++
++ err = e->ops[args->index](seq, args, do_size);
++ if (!err) {
++ Len(e) = seq->count;
++ break; /* success */
++ }
++
++ free_entry(e);
++ if (Allocated(e) > 0) {
++ Allocated(e) <<= 1;
++ if (unlikely(Allocated(e) >= (int)PAGE_SIZE))
++ Allocated(e) = 0;
++ } else
++ Allocated(e)--;
++ //Dbg("%d\n", Allocated(e));
++ }
++ kfree(seq);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* why does sysfs pass my parent kobject? */
++static struct dentry *find_me(struct dentry *parent, struct sysaufs_entry *e)
++{
++#if 1
++ struct dentry *dentry;
++ const char *name = Name(e);
++ const unsigned int len = strlen(name);
++
++ //Dbg("%.*s\n", DLNPair(parent));
++ spin_lock(&dcache_lock);
++ list_for_each_entry(dentry, &parent->d_subdirs, D_CHILD) {
++ //Dbg("%.*s\n", DLNPair(dentry));
++ if (len == dentry->d_name.len
++ && !strcmp(dentry->d_name.name, name)) {
++ spin_unlock(&dcache_lock);
++ return dentry;
++ }
++ }
++ spin_unlock(&dcache_lock);
++#endif
++ return NULL;
++}
++
++static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
++ size_t sz, struct sysaufs_args *args)
++{
++ ssize_t err;
++ loff_t len;
++ struct dentry *d;
++ struct sysaufs_entry *e;
++ int do_size;
++
++ LKTRTrace("{%d, %p}, offset %Ld, sz %lu\n",
++ args->index, args->sb, offset, (unsigned long)sz);
++
++ if (unlikely(!sz))
++ return 0;
++
++ err = 0;
++ d = NULL;
++ e = g_array + args->index;
++ if (args->sb)
++ e = stosi(args->sb)->si_sysaufs.array + args->index;
++
++ do_size = 1;
++ if (args->mtx)
++ mutex_lock(args->mtx);
++ if (unlikely(!Priv(e))) {
++ err = make(e, args, &do_size);
++ DEBUG_ON(Len(e) > INT_MAX);
++ if (do_size) {
++ d = find_me(kobj->dentry, e);
++ if (d)
++ i_size_write(d->d_inode, Len(e));
++ }
++ }
++
++ if (!err) {
++ err = len = Len(e) - offset;
++ LKTRTrace("%Ld\n", len);
++ if (len > 0) {
++ if (len > sz)
++ err = sz;
++ memcpy(buf, Priv(e) + offset, err);
++ }
++
++ if (!do_size)
++ free_entry(e);
++ }
++ if (args->mtx)
++ mutex_unlock(args->mtx);
++
++ TraceErr(err);
++ return err;
++}
++
++static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf,
++ loff_t offset, size_t sz,
++ struct sysaufs_args *args)
++{
++ struct dentry *d;
++ int allocated, len;
++ struct sysaufs_entry *e;
++
++ LKTRTrace("{%d, %p}\n", args->index, args->sb);
++
++ e = g_array + args->index;
++ if (args->sb)
++ e = stosi(args->sb)->si_sysaufs.array + args->index;
++
++ if (args->mtx)
++ mutex_lock(args->mtx);
++ if (Priv(e)) {
++ allocated = Allocated(e);
++ if (unlikely(allocated <= 0))
++ allocated = PAGE_SIZE << -allocated;
++ allocated >>= 1;
++ len = Len(e);
++
++ free_entry(e);
++ if (unlikely(len <= allocated)) {
++ if (Allocated(e) >= 0)
++ Allocated(e) = allocated;
++ else
++ Allocated(e)++;
++ }
++
++ d = find_me(kobj->dentry, e);
++ if (d && i_size_read(d->d_inode))
++ i_size_write(d->d_inode, 0);
++ }
++ if (args->mtx)
++ mutex_unlock(args->mtx);
++
++ return sz;
++}
++
++static sysaufs_op g_ops[] = {
++ [Brs] = make_brs,
++ [Stat] = make_stat,
++ [Config] = make_config
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define GSetEntry(index, name, init_size) \
++ SetEntry(g_array + index, name, init_size, g_ops)
++
++int __init sysaufs_init(void)
++{
++ int err;
++
++ GSetEntry(Brs, brs, 128);
++ GSetEntry(Stat, stat, 32);
++ GSetEntry(Config, config, 256);
++ err = reg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
++ TraceErr(err);
++ return err;
++}
++
++void __exit sysaufs_fin(void)
++{
++ mutex_lock(&aufs_sbilist_mtx);
++ unreg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
++ mutex_unlock(&aufs_sbilist_mtx);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef DbgDlgt
++int is_branch(struct super_block *h_sb)
++{
++ int found = 0;
++ struct aufs_sbinfo *sbinfo;
++
++ //Dbg("here\n");
++ mutex_lock(&aufs_sbilist_mtx);
++ list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++
++ sb = sbinfo->si_mnt->mnt_sb;
++ si_read_lock(sb);
++ bend = sbend(sb);
++ for (bindex = 0; !found && bindex <= bend; bindex++)
++ found = (h_sb == sbr_sb(sb, bindex));
++ si_read_unlock(sb);
++ }
++ mutex_unlock(&aufs_sbilist_mtx);
++ return found;
++}
++#endif
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sysaufs.h linux-2.6.22.1/fs/aufs/sysaufs.h
+--- linux-2.6.22.1.oorig/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/sysaufs.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,83 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: sysaufs.h,v 1.3 2007/05/14 06:27:18 sfjro Exp $ */
++
++#ifndef __SYSAUFS_H__
++#define __SYSAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++typedef struct kset au_subsys_t;
++#define au_subsys_to_kset(subsys) (subsys)
++#else
++typedef struct subsystem au_subsys_t;
++#define au_subsys_to_kset(subsys) ((subsys).kset)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* arguments for an entry under sysfs */
++struct sysaufs_args {
++ int index;
++ struct mutex *mtx;
++ struct super_block *sb;
++};
++
++typedef int (*sysaufs_op)(struct seq_file *seq, struct sysaufs_args *args,
++ int *do_size);
++
++/* an entry under sysfs */
++struct sysaufs_entry {
++ struct bin_attribute attr;
++ int allocated; /* zero minus means pages */
++ int err;
++ sysaufs_op *ops;
++};
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_sbinfo;
++#ifdef CONFIG_AUFS_SYSAUFS
++void sysaufs_add(struct aufs_sbinfo *sbinfo);
++void sysaufs_del(struct aufs_sbinfo *sbinfo);
++int __init sysaufs_init(void);
++void sysaufs_fin(void);
++void sysaufs_notify_remount(void);
++#else
++static inline void sysaufs_add(struct aufs_sbinfo *sbinfo)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_del(struct aufs_sbinfo *sbinfo)
++{
++ /* nothing */
++}
++#define sysaufs_init() 0
++#define sysaufs_fin() /* */
++#define sysaufs_notify_remount() /* */
++#endif /* CONFIG_AUFS_SYSAUFS */
++
++#endif /* __KERNEL__ */
++#endif /* __SYSAUFS_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vdir.c linux-2.6.22.1/fs/aufs/vdir.c
+--- linux-2.6.22.1.oorig/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/vdir.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,802 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vdir.c,v 1.22 2007/05/14 03:38:52 sfjro Exp $ */
++
++#include "aufs.h"
++
++static int calc_size(int namelen)
++{
++ int sz;
++
++ sz = sizeof(struct aufs_de) + namelen;
++ if (sizeof(ino_t) == sizeof(long)) {
++ const int mask = sizeof(ino_t) - 1;
++ if (sz & mask) {
++ sz += sizeof(ino_t);
++ sz &= ~mask;
++ }
++ } else {
++#if 0 // remove
++ BUG();
++ // this block will be discarded by optimizer.
++ int m;
++ m = sz % sizeof(ino_t);
++ if (m)
++ sz += sizeof(ino_t) - m;
++#endif
++ }
++
++ DEBUG_ON(sz % sizeof(ino_t));
++ return sz;
++}
++
++static int set_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->p - p->p) {
++ p->de->de_str.len = 0;
++ //smp_mb();
++ return 0;
++ }
++ return -1; // error
++}
++
++/* returns true or false */
++static int is_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->p - p->p)
++ return !p->de->de_str.len;
++ return 1;
++}
++
++static aufs_deblk_t *last_deblk(struct aufs_vdir *vdir)
++{
++ return vdir->vd_deblk[vdir->vd_nblk - 1];
++}
++
++void nhash_init(struct aufs_nhash *nhash)
++{
++ int i;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++)
++ INIT_HLIST_HEAD(nhash->heads + i);
++}
++
++struct aufs_nhash *nhash_new(gfp_t gfp)
++{
++ struct aufs_nhash *nhash;
++
++ nhash = kmalloc(sizeof(*nhash), gfp);
++ if (nhash) {
++ nhash_init(nhash);
++ return nhash;
++ }
++ return ERR_PTR(-ENOMEM);
++}
++
++void nhash_del(struct aufs_nhash *nhash)
++{
++ nhash_fin(nhash);
++ kfree(nhash);
++}
++
++void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src)
++{
++ int i;
++
++ TraceEnter();
++
++ //DbgWhlist(src);
++ *dst = *src;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ struct hlist_head *h;
++ h = dst->heads + i;
++ if (h->first)
++ h->first->pprev = &h->first;
++ INIT_HLIST_HEAD(src->heads + i);
++ }
++ //DbgWhlist(src);
++ //DbgWhlist(dst);
++ //smp_mb();
++}
++
++/* ---------------------------------------------------------------------- */
++
++void nhash_fin(struct aufs_nhash *whlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos, *n;
++
++ TraceEnter();
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
++ //hlist_del(pos);
++ kfree(tpos);
++ }
++ }
++}
++
++int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit)
++{
++ int n, i;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++
++ LKTRTrace("limit %d\n", limit);
++ //return 1;
++
++ n = 0;
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ if (tpos->wh_bindex == btgt && ++n > limit)
++ return 1;
++ }
++ return 0;
++}
++
++/* returns found(true) or not */
++int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen)
++{
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ head = whlist->heads + au_name_hash(name, namelen);
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ str = &tpos->wh_str;
++ LKTRTrace("%.*s\n", str->len, str->name);
++ if (str->len == namelen && !memcmp(str->name, name, namelen))
++ return 1;
++ }
++ return 0;
++}
++
++int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct aufs_destr *str;
++ struct aufs_wh *wh;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ err = -ENOMEM;
++ wh = kmalloc(sizeof(*wh) + namelen, GFP_KERNEL);
++ if (unlikely(!wh))
++ goto out;
++ err = 0;
++ wh->wh_bindex = bindex;
++ str = &wh->wh_str;
++ str->len = namelen;
++ memcpy(str->name, name, namelen);
++ hlist_add_head(&wh->wh_hash,
++ whlist->heads + au_name_hash(name, namelen));
++ //smp_mb();
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void free_vdir(struct aufs_vdir *vdir)
++{
++ aufs_deblk_t **deblk;
++
++ TraceEnter();
++
++ deblk = vdir->vd_deblk;
++ while (vdir->vd_nblk--) {
++ kfree(*deblk);
++ deblk++;
++ }
++ kfree(vdir->vd_deblk);
++ cache_free_vdir(vdir);
++}
++
++static int append_deblk(struct aufs_vdir *vdir)
++{
++ int err, sz, i;
++ aufs_deblk_t **o;
++ union aufs_deblk_p p, deblk_end;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ sz = sizeof(*o) * vdir->vd_nblk;
++ o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_KERNEL);
++ if (unlikely(!o))
++ goto out;
++ vdir->vd_deblk = o;
++ p.deblk = kmalloc(sizeof(*p.deblk), GFP_KERNEL);
++ if (p.deblk) {
++ i = vdir->vd_nblk++;
++ vdir->vd_deblk[i] = p.deblk;
++ vdir->vd_last.i = i;
++ vdir->vd_last.p.p = p.p;
++ deblk_end.deblk = p.deblk + 1;
++ err = set_deblk_end(&p, &deblk_end);
++ DEBUG_ON(err);
++ }
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static struct aufs_vdir *alloc_vdir(void)
++{
++ struct aufs_vdir *vdir;
++ int err;
++
++ TraceEnter();
++
++ err = -ENOMEM;
++ vdir = cache_alloc_vdir();
++ if (unlikely(!vdir))
++ goto out;
++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_KERNEL);
++ if (unlikely(!vdir->vd_deblk))
++ goto out_free;
++
++ vdir->vd_nblk = 0;
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ err = append_deblk(vdir);
++ if (!err)
++ return vdir; /* success */
++
++ kfree(vdir->vd_deblk);
++
++ out_free:
++ cache_free_vdir(vdir);
++ out:
++ vdir = ERR_PTR(err);
++ TraceErrPtr(vdir);
++ return vdir;
++}
++
++static int reinit_vdir(struct aufs_vdir *vdir)
++{
++ int err;
++ union aufs_deblk_p p, deblk_end;
++
++ TraceEnter();
++
++ while (vdir->vd_nblk > 1) {
++ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
++ vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
++ vdir->vd_nblk--;
++ }
++ p.deblk = vdir->vd_deblk[0];
++ deblk_end.deblk = p.deblk + 1;
++ err = set_deblk_end(&p, &deblk_end);
++ DEBUG_ON(err);
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ vdir->vd_last.i = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ //smp_mb();
++ //DbgVdir(vdir);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void free_dehlist(struct aufs_nhash *dehlist)
++{
++ int i;
++ struct hlist_head *head;
++ struct aufs_dehstr *tpos;
++ struct hlist_node *pos, *n;
++
++ TraceEnter();
++
++ for (i = 0; i < AUFS_NHASH_SIZE; i++) {
++ head = dehlist->heads + i;
++ hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
++ //hlist_del(pos);
++ cache_free_dehstr(tpos);
++ }
++ }
++}
++
++/* returns found(true) or not */
++static int test_known(struct aufs_nhash *delist, char *name, int namelen)
++{
++ struct hlist_head *head;
++ struct aufs_dehstr *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", namelen, name);
++
++ head = delist->heads + au_name_hash(name, namelen);
++ hlist_for_each_entry(tpos, pos, head, hash) {
++ str = tpos->str;
++ LKTRTrace("%.*s\n", str->len, str->name);
++ if (str->len == namelen && !memcmp(str->name, name, namelen))
++ return 1;
++ }
++ return 0;
++
++}
++
++static int append_de(struct aufs_vdir *vdir, char *name, int namelen, ino_t ino,
++ unsigned int d_type, struct aufs_nhash *delist)
++{
++ int err, sz;
++ union aufs_deblk_p p, *room, deblk_end;
++ struct aufs_dehstr *dehstr;
++
++ LKTRTrace("%.*s %d, i%lu, dt%u\n", namelen, name, namelen, ino, d_type);
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + 1;
++ room = &vdir->vd_last.p;
++ DEBUG_ON(room->p < p.p || deblk_end.p <= room->p
++ || !is_deblk_end(room, &deblk_end));
++
++ sz = calc_size(namelen);
++ if (unlikely(sz > deblk_end.p - room->p)) {
++ err = append_deblk(vdir);
++ if (unlikely(err))
++ goto out;
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + 1;
++ //smp_mb();
++ DEBUG_ON(room->p != p.p);
++ }
++
++ err = -ENOMEM;
++ dehstr = cache_alloc_dehstr();
++ if (unlikely(!dehstr))
++ goto out;
++ dehstr->str = &room->de->de_str;
++ hlist_add_head(&dehstr->hash,
++ delist->heads + au_name_hash(name, namelen));
++
++ room->de->de_ino = ino;
++ room->de->de_type = d_type;
++ room->de->de_str.len = namelen;
++ memcpy(room->de->de_str.name, name, namelen);
++
++ err = 0;
++ room->p += sz;
++ if (unlikely(set_deblk_end(room, &deblk_end)))
++ err = append_deblk(vdir);
++ //smp_mb();
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct fillvdir_arg {
++ struct file *file;
++ struct aufs_vdir *vdir;
++ struct aufs_nhash *delist;
++ struct aufs_nhash *whlist;
++ aufs_bindex_t bindex;
++ int err;
++ int called;
++};
++
++static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
++ filldir_ino_t h_ino, unsigned int d_type)
++{
++ struct fillvdir_arg *arg = __arg;
++ char *name = (void*)__name;
++ aufs_bindex_t bindex, bend;
++ struct xino xino;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, namelen %d, i%Lu, dt%u\n",
++ namelen, name, namelen, (u64)h_ino, d_type);
++
++ sb = arg->file->f_dentry->d_sb;
++ bend = arg->bindex;
++ arg->err = 0;
++ arg->called++;
++ //smp_mb();
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ for (bindex = 0; bindex < bend; bindex++)
++ if (test_known(arg->delist + bindex, name, namelen)
++ || test_known_wh(arg->whlist + bindex, name,
++ namelen))
++ goto out; /* already exists or whiteouted */
++
++ arg->err = xino_read(sb, bend, h_ino, &xino);
++ if (!arg->err && !xino.ino) {
++ //struct inode *h_inode;
++ xino.ino = xino_new_ino(sb);
++ if (unlikely(!xino.ino))
++ arg->err = -EIO;
++#if 0
++ //xino.h_gen = AuXino_INVALID_HGEN;
++ h_inode = ilookup(sbr_sb(sb, bend), h_ino);
++ if (h_inode) {
++ if (!is_bad_inode(h_inode)) {
++ xino.h_gen = h_inode->i_generation;
++ WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ }
++ iput(h_inode);
++ }
++#endif
++ arg->err = xino_write(sb, bend, h_ino, &xino);
++ }
++ if (!arg->err)
++ arg->err = append_de(arg->vdir, name, namelen, xino.ino,
++ d_type, arg->delist + bend);
++ } else {
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ for (bindex = 0; bindex < bend; bindex++)
++ if (test_known_wh(arg->whlist + bend, name, namelen))
++ goto out; /* already whiteouted */
++ arg->err = append_wh(arg->whlist + bend, name, namelen, bend);
++ }
++
++ out:
++ if (!arg->err)
++ arg->vdir->vd_jiffy = jiffies;
++ //smp_mb();
++ TraceErr(arg->err);
++ return arg->err;
++}
++
++static int read_vdir(struct file *file, int may_read)
++{
++ int err, do_read, dlgt;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_vdir *vdir, *allocated;
++ unsigned long expire;
++ struct fillvdir_arg arg;
++ aufs_bindex_t bindex, bend, bstart;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, may %d\n", DLNPair(dentry), may_read);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++
++ err = 0;
++ allocated = NULL;
++ do_read = 0;
++ sb = inode->i_sb;
++ expire = stosi(sb)->si_rdcache;
++ vdir = ivdir(inode);
++ if (!vdir) {
++ DEBUG_ON(fvdir_cache(file));
++ do_read = 1;
++ vdir = alloc_vdir();
++ err = PTR_ERR(vdir);
++ if (IS_ERR(vdir))
++ goto out;
++ err = 0;
++ allocated = vdir;
++ } else if (may_read
++ && (inode->i_version != vdir->vd_version
++ || time_after(jiffies, vdir->vd_jiffy + expire))) {
++ LKTRTrace("iver %lu, vdver %lu, exp %lu\n",
++ inode->i_version, vdir->vd_version,
++ vdir->vd_jiffy + expire);
++ do_read = 1;
++ err = reinit_vdir(vdir);
++ if (unlikely(err))
++ goto out;
++ }
++ //DbgVdir(vdir); goto out;
++
++ if (!do_read)
++ return 0; /* success */
++
++ err = -ENOMEM;
++ bend = fbend(file);
++ arg.delist = kmalloc(sizeof(*arg.delist) * (bend + 1), GFP_KERNEL);
++ if (unlikely(!arg.delist))
++ goto out_vdir;
++ arg.whlist = kmalloc(sizeof(*arg.whlist) * (bend + 1), GFP_KERNEL);
++ if (unlikely(!arg.whlist))
++ goto out_delist;
++ err = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ nhash_init(arg.delist + bindex);
++ nhash_init(arg.whlist + bindex);
++ }
++
++ dlgt = need_dlgt(sb);
++ arg.file = file;
++ arg.vdir = vdir;
++ bstart = fbstart(file);
++ for (bindex = bstart; !err && bindex <= bend; bindex++) {
++ struct file *hf;
++ struct inode *h_inode;
++
++ hf = au_h_fptr_i(file, bindex);
++ if (!hf)
++ continue;
++
++ h_inode = hf->f_dentry->d_inode;
++ //hf->f_pos = 0;
++ arg.bindex = bindex;
++ do {
++ arg.err = 0;
++ arg.called = 0;
++ //smp_mb();
++ err = vfsub_readdir(hf, fillvdir, &arg, dlgt);
++ if (err >= 0)
++ err = arg.err;
++ } while (!err && arg.called);
++ }
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ free_dehlist(arg.delist + bindex);
++ nhash_fin(arg.whlist + bindex);
++ }
++ kfree(arg.whlist);
++
++ out_delist:
++ kfree(arg.delist);
++ out_vdir:
++ if (!err) {
++ //file->f_pos = 0;
++ vdir->vd_version = inode->i_version;
++ vdir->vd_last.i = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ if (allocated)
++ set_ivdir(inode, allocated);
++ } else if (allocated)
++ free_vdir(allocated);
++ //DbgVdir(vdir); goto out;
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static int copy_vdir(struct aufs_vdir *tgt, struct aufs_vdir *src)
++{
++ int err, i, rerr, n;
++
++ TraceEnter();
++ DEBUG_ON(tgt->vd_nblk != 1);
++ //DbgVdir(tgt);
++
++ err = -ENOMEM;
++ if (tgt->vd_nblk < src->vd_nblk) {
++ aufs_deblk_t **p;
++ p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
++ sizeof(*p) * src->vd_nblk, GFP_KERNEL);
++ if (unlikely(!p))
++ goto out;
++ tgt->vd_deblk = p;
++ }
++
++ n = tgt->vd_nblk = src->vd_nblk;
++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AUFS_DEBLK_SIZE);
++ //tgt->vd_last.i = 0;
++ //tgt->vd_last.p.deblk = tgt->vd_deblk[0];
++ tgt->vd_version = src->vd_version;
++ tgt->vd_jiffy = src->vd_jiffy;
++
++ for (i = 1; i < n; i++) {
++ tgt->vd_deblk[i] = kmalloc(AUFS_DEBLK_SIZE, GFP_KERNEL);
++ if (tgt->vd_deblk[i])
++ memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
++ AUFS_DEBLK_SIZE);
++ else
++ goto out;
++ }
++ //smp_mb();
++ //DbgVdir(tgt);
++ return 0; /* success */
++
++ out:
++ rerr = reinit_vdir(tgt);
++ BUG_ON(rerr);
++ TraceErr(err);
++ return err;
++}
++
++int au_init_vdir(struct file *file)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct aufs_vdir *vdir_cache, *allocated;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ FiMustWriteLock(file);
++ inode = dentry->d_inode;
++ IiMustWriteLock(inode);
++ DEBUG_ON(!S_ISDIR(inode->i_mode));
++
++ err = read_vdir(file, !file->f_pos);
++ if (unlikely(err))
++ goto out;
++ //DbgVdir(ivdir(inode)); goto out;
++
++ allocated = NULL;
++ vdir_cache = fvdir_cache(file);
++ if (!vdir_cache) {
++ vdir_cache = alloc_vdir();
++ err = PTR_ERR(vdir_cache);
++ if (IS_ERR(vdir_cache))
++ goto out;
++ allocated = vdir_cache;
++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
++ err = reinit_vdir(vdir_cache);
++ if (unlikely(err))
++ goto out;
++ } else
++ return 0; /* success */
++ //err = 0; DbgVdir(vdir_cache); goto out;
++
++ err = copy_vdir(vdir_cache, ivdir(inode));
++ if (!err) {
++ file->f_version = inode->i_version;
++ if (allocated)
++ set_fvdir_cache(file, allocated);
++ } else if (allocated)
++ free_vdir(allocated);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++static loff_t calc_offset(struct aufs_vdir *vdir)
++{
++ loff_t offset;
++ union aufs_deblk_p p;
++
++ p.deblk = vdir->vd_deblk[vdir->vd_last.i];
++ offset = vdir->vd_last.p.p - p.p;
++ offset += sizeof(*p.deblk) * vdir->vd_last.i;
++ return offset;
++}
++
++/* returns true or false */
++static int seek_vdir(struct file *file)
++{
++ int valid, i, n;
++ struct dentry *dentry;
++ struct aufs_vdir *vdir_cache;
++ loff_t offset;
++ union aufs_deblk_p p, deblk_end;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ vdir_cache = fvdir_cache(file);
++ DEBUG_ON(!vdir_cache);
++ //DbgVdir(vdir_cache);
++
++ valid = 1;
++ offset = calc_offset(vdir_cache);
++ LKTRTrace("offset %Ld\n", offset);
++ if (file->f_pos == offset)
++ goto out;
++
++ vdir_cache->vd_last.i = 0;
++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
++ if (!file->f_pos)
++ goto out;
++
++ valid = 0;
++ i = file->f_pos / AUFS_DEBLK_SIZE;
++ LKTRTrace("i %d\n", i);
++ if (i >= vdir_cache->vd_nblk)
++ goto out;
++
++ n = vdir_cache->vd_nblk;
++ //DbgVdir(vdir_cache);
++ for (; i < n; i++) {
++ p.deblk = vdir_cache->vd_deblk[i];
++ deblk_end.deblk = p.deblk + 1;
++ offset = i * AUFS_DEBLK_SIZE;
++ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
++ int l;
++ l = calc_size(p.de->de_str.len);
++ offset += l;
++ p.p += l;
++ }
++ if (!is_deblk_end(&p, &deblk_end)) {
++ valid = 1;
++ vdir_cache->vd_last.i = i;
++ vdir_cache->vd_last.p = p;
++ break;
++ }
++ }
++
++ out:
++ //smp_mb();
++ //DbgVdir(vdir_cache);
++ TraceErr(!valid);
++ return valid;
++}
++
++int au_fill_de(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err, l;
++ struct dentry *dentry;
++ struct aufs_vdir *vdir_cache;
++ struct aufs_de *de;
++ union aufs_deblk_p deblk_end;
++
++ dentry = file->f_dentry;
++ LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
++ vdir_cache = fvdir_cache(file);
++ DEBUG_ON(!vdir_cache);
++ //DbgVdir(vdir_cache);
++
++ if (!seek_vdir(file))
++ return 0;
++
++ while (1) {
++ deblk_end.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
++ de = vdir_cache->vd_last.p.de;
++ LKTRTrace("%.*s, off%Ld, i%lu, dt%d\n",
++ de->de_str.len, de->de_str.name,
++ file->f_pos, de->de_ino, de->de_type);
++ err = filldir(dirent, de->de_str.name, de->de_str.len,
++ file->f_pos, de->de_ino, de->de_type);
++ if (unlikely(err)) {
++ TraceErr(err);
++ //return err;
++ //todo: ignore the error caused by udba.
++ return 0;
++ }
++
++ l = calc_size(de->de_str.len);
++ vdir_cache->vd_last.p.p += l;
++ file->f_pos += l;
++ }
++ if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
++ vdir_cache->vd_last.i++;
++ vdir_cache->vd_last.p.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
++ file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
++ * vdir_cache->vd_last.i;
++ continue;
++ }
++ break;
++ }
++
++ //smp_mb();
++ return 0;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vfsub.c linux-2.6.22.1/fs/aufs/vfsub.c
+--- linux-2.6.22.1.oorig/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/vfsub.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,665 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vfsub.c,v 1.5 2007/04/23 00:55:06 sfjro Exp $ */
++// I'm going to slightly mad
++
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++struct permission_args {
++ int *errp;
++ struct inode *inode;
++ int mask;
++ struct nameidata *nd;
++};
++
++static void call_permission(void *args)
++{
++ struct permission_args *a = args;
++ *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
++}
++
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_permission(inode, mask, nd);
++ else {
++ int err;
++ struct permission_args args = {
++ .errp = &err,
++ .inode = inode,
++ .mask = mask,
++ .nd = nd
++ };
++ au_wkq_wait(call_permission, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct create_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++ struct nameidata *nd;
++};
++
++static void call_create(void *args)
++{
++ struct create_args *a = args;
++ *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
++}
++
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_create(dir, dentry, mode, nd);
++ else {
++ int err;
++ struct create_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode,
++ .nd = nd
++ };
++ au_wkq_wait(call_create, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct symlink_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ const char *symname;
++ int mode;
++};
++
++static void call_symlink(void *args)
++{
++ struct symlink_args *a = args;
++ *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
++}
++
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_symlink(dir, dentry, symname, mode);
++ else {
++ int err;
++ struct symlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .symname = symname,
++ .mode = mode
++ };
++ au_wkq_wait(call_symlink, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct mknod_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++ dev_t dev;
++};
++
++static void call_mknod(void *args)
++{
++ struct mknod_args *a = args;
++ *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
++}
++
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_mknod(dir, dentry, mode, dev);
++ else {
++ int err;
++ struct mknod_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode,
++ .dev = dev
++ };
++ au_wkq_wait(call_mknod, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct mkdir_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++ int mode;
++};
++
++static void call_mkdir(void *args)
++{
++ struct mkdir_args *a = args;
++ *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
++}
++
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_mkdir(dir, dentry, mode);
++ else {
++ int err;
++ struct mkdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry,
++ .mode = mode
++ };
++ au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct link_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *src_dentry, *dentry;
++};
++
++static void call_link(void *args)
++{
++ struct link_args *a = args;
++ *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
++}
++
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_link(src_dentry, dir, dentry);
++ else {
++ int err;
++ struct link_args args = {
++ .errp = &err,
++ .src_dentry = src_dentry,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_link, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct rename_args {
++ int *errp;
++ struct inode *src_dir, *dir;
++ struct dentry *src_dentry, *dentry;
++};
++
++static void call_rename(void *args)
++{
++ struct rename_args *a = args;
++ *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
++ a->dentry);
++}
++
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
++ else {
++ int err;
++ struct rename_args args = {
++ .errp = &err,
++ .src_dir = src_dir,
++ .src_dentry = src_dentry,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_rename, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct rmdir_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++};
++
++static void call_rmdir(void *args)
++{
++ struct rmdir_args *a = args;
++ *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
++}
++
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_rmdir(dir, dentry);
++ else {
++ int err;
++ struct rmdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry
++ };
++ au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct read_args {
++ ssize_t *errp;
++ struct file *file;
++ union {
++ void *kbuf;
++ char __user *ubuf;
++ };
++ size_t count;
++ loff_t *ppos;
++};
++
++static void call_read_k(void *args)
++{
++ struct read_args *a = args;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(a->file->f_dentry), (unsigned long)a->count,
++ *a->ppos);
++ *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
++}
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_read_u(file, ubuf, count, ppos);
++ else {
++ ssize_t err, read;
++ struct read_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++
++ if (unlikely(!count))
++ return 0;
++
++ /*
++ * workaround an application bug.
++ * generally, read(2) or write(2) may return the value shorter
++ * than requested. But many applications don't support it,
++ * for example bash.
++ */
++ err = -ENOMEM;
++ if (args.count > PAGE_SIZE)
++ args.count = PAGE_SIZE;
++ args.kbuf = kmalloc(args.count, GFP_KERNEL);
++ if (unlikely(!args.kbuf))
++ goto out;
++
++ read = 0;
++ do {
++ au_wkq_wait(call_read_k, &args, /*dlgt*/1);
++ if (unlikely(err > 0
++ && copy_to_user(ubuf, args.kbuf, err))) {
++ err = -EFAULT;
++ goto out_free;
++ } else if (!err)
++ break;
++ else if (unlikely(err < 0))
++ goto out_free;
++ count -= err;
++ /* do not read too much because of file i/o pointer */
++ if (unlikely(count < args.count))
++ args.count = count;
++ ubuf += err;
++ read += err;
++ } while (count);
++ smp_mb();
++ err = read;
++
++ out_free:
++ kfree(args.kbuf);
++ out:
++ return err;
++ }
++}
++
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_read_k(file, kbuf, count, ppos);
++ else {
++ ssize_t err;
++ struct read_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++ args.kbuf = kbuf;
++ au_wkq_wait(call_read_k, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct write_args {
++ ssize_t *errp;
++ struct file *file;
++ union {
++ void *kbuf;
++ const char __user *ubuf;
++ };
++ void *buf;
++ size_t count;
++ loff_t *ppos;
++};
++
++static void call_write_k(void *args)
++{
++ struct write_args *a = args;
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(a->file->f_dentry), (unsigned long)a->count,
++ *a->ppos);
++ *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
++}
++
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_write_u(file, ubuf, count, ppos);
++ else {
++ ssize_t err, written;
++ struct write_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++
++ if (unlikely(!count))
++ return 0;
++
++ /*
++ * workaround an application bug.
++ * generally, read(2) or write(2) may return the value shorter
++ * than requested. But many applications don't support it,
++ * for example bash.
++ */
++ err = -ENOMEM;
++ if (args.count > PAGE_SIZE)
++ args.count = PAGE_SIZE;
++ args.kbuf = kmalloc(args.count, GFP_KERNEL);
++ if (unlikely(!args.kbuf))
++ goto out;
++
++ written = 0;
++ do {
++ if (unlikely(copy_from_user(args.kbuf, ubuf, args.count))) {
++ err = -EFAULT;
++ goto out_free;
++ }
++
++ au_wkq_wait(call_write_k, &args, /*dlgt*/1);
++ if (err > 0) {
++ count -= err;
++ if (count < args.count)
++ args.count = count;
++ ubuf += err;
++ written += err;
++ } else if (!err)
++ break;
++ else if (unlikely(err < 0))
++ goto out_free;
++ } while (count);
++ err = written;
++
++ out_free:
++ kfree(args.kbuf);
++ out:
++ return err;
++ }
++}
++
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_write_k(file, kbuf, count, ppos);
++ else {
++ ssize_t err;
++ struct write_args args = {
++ .errp = &err,
++ .file = file,
++ .count = count,
++ .ppos = ppos
++ };
++ args.kbuf = kbuf;
++ au_wkq_wait(call_write_k, &args, /*dlgt*/1);
++ return err;
++ }
++}
++
++struct readdir_args {
++ int *errp;
++ struct file *file;
++ filldir_t filldir;
++ void *arg;
++};
++
++static void call_readdir(void *args)
++{
++ struct readdir_args *a = args;
++ *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
++}
++
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
++{
++ if (!dlgt)
++ return do_vfsub_readdir(file, filldir, arg);
++ else {
++ int err;
++ struct readdir_args args = {
++ .errp = &err,
++ .file = file,
++ .filldir = filldir,
++ .arg = arg
++ };
++ au_wkq_wait(call_readdir, &args, /*dlgt*/1);
++ return err;
++ }
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++/* ---------------------------------------------------------------------- */
++
++struct notify_change_args {
++ int *errp;
++ struct dentry *h_dentry;
++ struct iattr *ia;
++};
++
++static void call_notify_change(void *args)
++{
++ struct notify_change_args *a = args;
++ struct inode *h_inode;
++
++ LKTRTrace("%.*s, ia_valid 0x%x\n",
++ DLNPair(a->h_dentry), a->ia->ia_valid);
++ h_inode = a->h_dentry->d_inode;
++ IMustLock(h_inode);
++
++ *a->errp = -EPERM;
++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ lockdep_off();
++ *a->errp = notify_change(a->h_dentry, a->ia);
++ lockdep_on();
++ }
++ TraceErr(*a->errp);
++}
++
++int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt)
++{
++ int err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .h_dentry = dentry,
++ .ia = ia
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_notify_change(&args);
++#else
++ if (!dlgt)
++ call_notify_change(&args);
++ else
++ au_wkq_wait(call_notify_change, &args, /*dlgt*/1);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct unlink_args {
++ int *errp;
++ struct inode *dir;
++ struct dentry *dentry;
++};
++
++static void call_unlink(void *args)
++{
++ struct unlink_args *a = args;
++ struct inode *h_inode;
++ const int stop_sillyrename = (au_is_nfs(a->dentry->d_sb)
++ && atomic_read(&a->dentry->d_count) == 1);
++
++ LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
++ DLNPair(a->dentry), stop_sillyrename,
++ atomic_read(&a->dentry->d_count));
++ IMustLock(a->dir);
++
++ if (!stop_sillyrename)
++ dget(a->dentry);
++ h_inode = a->dentry->d_inode;
++ if (h_inode)
++ atomic_inc(&h_inode->i_count);
++#if 0 // partial testing
++ {
++ struct qstr *name = &a->dentry->d_name;
++ if (name->len == sizeof(AUFS_XINO_FNAME) - 1
++ && !strncmp(name->name, AUFS_XINO_FNAME, name->len)) {
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, a->dentry);
++ lockdep_on();
++ } else
++ err = -1;
++ }
++#else
++ // vfs_unlink() locks inode
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, a->dentry);
++ lockdep_on();
++#endif
++
++ if (!stop_sillyrename)
++ dput(a->dentry);
++ if (h_inode)
++ iput(h_inode);
++
++ TraceErr(*a->errp);
++}
++
++/*
++ * @dir: must be locked.
++ * @dentry: target dentry.
++ */
++int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ int err;
++ struct unlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .dentry = dentry
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_unlink(&args);
++#else
++ if (!dlgt)
++ call_unlink(&args);
++ else
++ au_wkq_wait(call_unlink, &args, /*dlgt*/1);
++#endif
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct statfs_args {
++ int *errp;
++ void *arg;
++ struct kstatfs *buf;
++};
++
++static void call_statfs(void *args)
++{
++ struct statfs_args *a = args;
++ *a->errp = vfs_statfs(a->arg, a->buf);
++}
++
++int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
++{
++ int err;
++ struct statfs_args args = {
++ .errp = &err,
++ .arg = arg,
++ .buf = buf
++ };
++
++#ifndef CONFIG_AUFS_DLGT
++ call_statfs(&args);
++#else
++ if (!dlgt)
++ call_statfs(&args);
++ else
++ au_wkq_wait(call_statfs, &args, /*dlgt*/1);
++#endif
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vfsub.h linux-2.6.22.1/fs/aufs/vfsub.h
+--- linux-2.6.22.1.oorig/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/vfsub.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,427 @@
++/*
++ * Copyright (C) 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: vfsub.h,v 1.8 2007/05/14 03:39:10 sfjro Exp $ */
++
++#ifndef __AUFS_VFSUB_H__
++#define __AUFS_VFSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include "wkq.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* simple abstractions, for future use */
++static inline
++int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
++{
++ LKTRTrace("i%lu, mask 0x%x, nd %p\n", inode->i_ino, mask, nd);
++#if 0
++#else
++ return permission(inode, mask, nd);
++#endif
++}
++
++static inline
++struct file *vfsub_filp_open(const char *path, int oflags, int mode)
++{
++ struct file *err;
++
++ LKTRTrace("%s\n", path);
++
++ lockdep_off();
++ err = filp_open(path, oflags, mode);
++ lockdep_on();
++ return err;
++}
++
++static inline
++int vfsub_path_lookup(const char *name, unsigned int flags,
++ struct nameidata *nd)
++{
++ int err;
++
++ LKTRTrace("%s\n", name);
++
++ //lockdep_off();
++ err = path_lookup(name, flags, nd);
++ //lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_create(dir, dentry, mode, nd);
++#endif
++}
++
++static inline
++int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname, int mode)
++{
++ LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
++ dir->i_ino, DLNPair(dentry), symname, mode);
++#if 0
++#else
++ return vfs_symlink(dir, dentry, symname, mode);
++#endif
++}
++
++static inline
++int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
++ dev_t dev)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_mknod(dir, dentry, mode, dev);
++#endif
++}
++
++static inline
++int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("%.*s, i%lu, %.*s\n",
++ DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_link(src_dentry, dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
++ src_dir->i_ino, DLNPair(src_dentry),
++ dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_rename(src_dir, src_dentry, dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
++#if 0
++#else
++ return vfs_mkdir(dir, dentry, mode);
++#endif
++}
++
++static inline int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err;
++
++ LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_rmdir(dir, dentry);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)count, *ppos);
++
++ /* nfs uses some locks */
++ lockdep_off();
++#if 0
++#else
++ err = vfs_read(file, ubuf, count, ppos);
++#endif
++ lockdep_on();
++ return err;
++}
++
++// kernel_read() ??
++static inline
++ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = do_vfsub_read_u(file, (char __user*)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++static inline
++ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)count, *ppos);
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_write(file, ubuf, count, ppos);
++#endif
++ lockdep_on();
++ return err;
++}
++
++static inline
++ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = do_vfsub_write_u(file, (const char __user*)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++static inline
++int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
++{
++ int err;
++
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_readdir(file, filldir, arg);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
++{
++ loff_t err;
++
++ LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
++
++ lockdep_off();
++#if 0
++#else
++ err = vfs_llseek(file, offset, origin);
++#endif
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++static inline int need_dlgt(struct super_block *sb)
++{
++ return (au_flag_test(sb, AuFlag_DLGT) && !is_au_wkq(current));
++}
++
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt);
++
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt);
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt);
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt);
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt);
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt);
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt);
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt);
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt);
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt);
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt);
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt);
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
++
++#else
++
++static inline int need_dlgt(struct super_block *sb)
++{
++ return 0;
++}
++
++static inline
++int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
++ int dlgt)
++{
++ return do_vfsub_permission(inode, mask, nd);
++}
++
++static inline
++int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd, int dlgt)
++{
++ return do_vfsub_create(dir, dentry, mode, nd);
++}
++
++static inline
++int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
++ int mode, int dlgt)
++{
++ return do_vfsub_symlink(dir, dentry, symname, mode);
++}
++
++static inline
++int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
++ int dlgt)
++{
++ return do_vfsub_mknod(dir, dentry, mode, dev);
++}
++
++static inline
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_link(src_dentry, dir, dentry);
++}
++
++static inline
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
++}
++
++static inline
++int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
++ int dlgt)
++{
++ return do_vfsub_mkdir(dir, dentry, mode);
++}
++
++static inline
++int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
++{
++ return do_vfsub_rmdir(dir, dentry);
++}
++
++static inline
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ return do_vfsub_read_u(file, ubuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ return do_vfsub_read_k(file, kbuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos, int dlgt)
++{
++ return do_vfsub_write_u(file, ubuf, count, ppos);
++}
++
++static inline
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
++ int dlgt)
++{
++ return do_vfsub_write_k(file, kbuf, count, ppos);
++}
++
++static inline
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
++{
++ return do_vfsub_readdir(file, filldir, arg);
++}
++#endif /* CONFIG_AUFS_DLGT */
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
++{
++ struct dentry *d;
++
++ lockdep_off();
++ d = lock_rename(d1, d2);
++ lockdep_on();
++ return d;
++}
++
++static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
++{
++ lockdep_off();
++ unlock_rename(d1, d2);
++ lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt);
++int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt);
++int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_VFSUB_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/whout.c linux-2.6.22.1/fs/aufs/whout.c
+--- linux-2.6.22.1.oorig/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/whout.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,933 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: whout.c,v 1.14 2007/05/14 03:40:40 sfjro Exp $ */
++
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/random.h>
++#include <linux/security.h>
++#include "aufs.h"
++
++#define WH_MASK S_IRUGO
++
++/* If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++static struct qstr diropq_name = {
++ .name = AUFS_WH_DIROPQ,
++ .len = sizeof(AUFS_WH_DIROPQ) - 1
++};
++
++/*
++ * generate whiteout name, which is NOT terminated by NULL.
++ * @name: original d_name.name
++ * @len: original d_name.len
++ * @wh: whiteout qstr
++ * returns zero when succeeds, otherwise error.
++ * succeeded value as wh->name should be freed by au_free_whname().
++ */
++int au_alloc_whname(const char *name, int len, struct qstr *wh)
++{
++ char *p;
++
++ DEBUG_ON(!name || !len || !wh);
++
++ if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
++ return -ENAMETOOLONG;
++
++ wh->len = len + AUFS_WH_PFX_LEN;
++ wh->name = p = kmalloc(wh->len, GFP_KERNEL);
++ //if (LktrCond) {kfree(p); wh->name = p = NULL;}
++ if (p) {
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ memcpy(p + AUFS_WH_PFX_LEN, name, len);
++ //smp_mb();
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++void au_free_whname(struct qstr *wh)
++{
++ DEBUG_ON(!wh || !wh->name);
++ kfree(wh->name);
++#ifdef CONFIG_AUFS_DEBUG
++ wh->name = NULL;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the @wh_name exists under @hidden_parent.
++ * @try_sio specifies the necessary of super-io.
++ */
++int is_wh(struct dentry *hidden_parent, struct qstr *wh_name, int try_sio,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct dentry *wh_dentry;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(hidden_parent),
++ wh_name->len, wh_name->name, lkup->nfsmnt, lkup->dlgt);
++ hidden_dir = hidden_parent->d_inode;
++ DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ if (!try_sio)
++ wh_dentry = lkup_one(wh_name->name, hidden_parent,
++ wh_name->len, lkup);
++ else
++ wh_dentry = sio_lkup_one(wh_name->name, hidden_parent,
++ wh_name->len, lkup);
++ //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ err = 0;
++ if (!wh_dentry->d_inode)
++ goto out_wh; /* success */
++
++ err = 1;
++ if (S_ISREG(wh_dentry->d_inode->i_mode))
++ goto out_wh; /* success */
++
++ err = -EIO;
++ IOErr("%.*s Invalid whiteout entry type 0%o.\n",
++ DLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * test if the @hidden_dentry sets opaque or not.
++ */
++int is_diropq(struct dentry *hidden_dentry, struct lkup_args *lkup)
++{
++ int err;
++ struct inode *hidden_dir;
++
++ LKTRTrace("dentry %.*s\n", DLNPair(hidden_dentry));
++ hidden_dir = hidden_dentry->d_inode;
++ DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ err = is_wh(hidden_dentry, &diropq_name, /*try_sio*/1, lkup);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * returns a negative dentry whose name is unique and temporary.
++ */
++struct dentry *lkup_whtmp(struct dentry *hidden_parent, struct qstr *prefix,
++ struct lkup_args *lkup)
++{
++#define HEX_LEN 4
++ struct dentry *dentry;
++ int len, i;
++ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
++ + HEX_LEN + 1], *name, *p;
++ static unsigned char cnt;
++
++ LKTRTrace("hp %.*s, prefix %.*s\n",
++ DLNPair(hidden_parent), prefix->len, prefix->name);
++ DEBUG_ON(!hidden_parent->d_inode);
++ IMustLock(hidden_parent->d_inode);
++
++ name = defname;
++ len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
++ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
++ dentry = ERR_PTR(-ENAMETOOLONG);
++ if (unlikely(len >= PATH_MAX))
++ goto out;
++ dentry = ERR_PTR(-ENOMEM);
++ name = kmalloc(len + 1, GFP_KERNEL);
++ //if (LktrCond) {kfree(name); name = NULL;}
++ if (unlikely(!name))
++ goto out;
++ }
++
++ // doubly whiteout-ed
++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
++ p = name + AUFS_WH_PFX_LEN * 2;
++ memcpy(p, prefix->name, prefix->len);
++ p += prefix->len;
++ *p++ = '.';
++ DEBUG_ON(name + len + 1 - p <= HEX_LEN);
++
++ for (i = 0; i < 3; i++) {
++ sprintf(p, "%.*d", HEX_LEN, cnt++);
++ dentry = sio_lkup_one(name, hidden_parent, len, lkup);
++ //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
++ if (unlikely(IS_ERR(dentry) || !dentry->d_inode))
++ goto out_name;
++ dput(dentry);
++ }
++ //Warn("could not get random name\n");
++ dentry = ERR_PTR(-EEXIST);
++ Dbg("%.*s\n", len, name);
++ BUG();
++
++ out_name:
++ if (unlikely(name != defname))
++ kfree(name);
++ out:
++ TraceErrPtr(dentry);
++ return dentry;
++#undef HEX_LEN
++}
++
++/*
++ * rename the @dentry of @bindex to the whiteouted temporary name.
++ */
++int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct inode *hidden_dir;
++ struct dentry *hidden_dentry, *hidden_parent, *tmp_dentry;
++ struct super_block *sb;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry || !hidden_dentry->d_inode);
++ hidden_parent = hidden_dentry->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ sb = dentry->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = need_dlgt(sb);
++ tmp_dentry = lkup_whtmp(hidden_parent, &hidden_dentry->d_name, &lkup);
++ //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
++ err = PTR_ERR(tmp_dentry);
++ if (!IS_ERR(tmp_dentry)) {
++ /* under the same dir, no need to lock_rename() */
++ err = vfsub_rename(hidden_dir, hidden_dentry,
++ hidden_dir, tmp_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1; //unavailable
++ TraceErr(err);
++ dput(tmp_dentry);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_unlink_wh_dentry(struct inode *hidden_dir, struct dentry *wh_dentry,
++ struct dentry *dentry, int dlgt)
++{
++ int err;
++
++ LKTRTrace("hi%lu, wh %.*s, d %p\n", hidden_dir->i_ino,
++ DLNPair(wh_dentry), dentry);
++ DEBUG_ON((dentry && dbwh(dentry) == -1)
++ || !wh_dentry->d_inode
++ || !S_ISREG(wh_dentry->d_inode->i_mode));
++ IMustLock(hidden_dir);
++
++ err = vfsub_unlink(hidden_dir, wh_dentry, dlgt);
++ //if (LktrCond) err = -1; // unavailable
++ if (!err && dentry)
++ set_dbwh(dentry, -1);
++
++ TraceErr(err);
++ return err;
++}
++
++static int unlink_wh_name(struct dentry *hidden_parent, struct qstr *wh,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct inode *hidden_dir;
++ struct dentry *hidden_dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(wh));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ // au_test_perm() is already done
++ hidden_dentry = lkup_one(wh->name, hidden_parent, wh->len, lkup);
++ //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
++ if (!IS_ERR(hidden_dentry)) {
++ err = 0;
++ if (hidden_dentry->d_inode)
++ err = vfsub_unlink(hidden_dir, hidden_dentry,
++ lkup->dlgt);
++ dput(hidden_dentry);
++ } else
++ err = PTR_ERR(hidden_dentry);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void clean_wh(struct inode *h_dir, struct dentry *wh)
++{
++ TraceEnter();
++ if (wh->d_inode) {
++ int err = vfsub_unlink(h_dir, wh, /*dlgt*/0);
++ if (unlikely(err))
++ Warn("failed unlink %.*s (%d), ignored.\n",
++ DLNPair(wh), err);
++ }
++}
++
++static void clean_plink(struct inode *h_dir, struct dentry *plink)
++{
++ TraceEnter();
++ if (plink->d_inode) {
++ int err = vfsub_rmdir(h_dir, plink, /*dlgt*/0);
++ if (unlikely(err))
++ Warn("failed rmdir %.*s (%d), ignored.\n",
++ DLNPair(plink), err);
++ }
++}
++
++static int test_linkable(struct inode *h_dir)
++{
++ if (h_dir->i_op && h_dir->i_op->link)
++ return 0;
++ return -ENOSYS;
++}
++
++static int plink_dir(struct inode *h_dir, struct dentry *plink)
++{
++ int err;
++
++ err = -EEXIST;
++ if (!plink->d_inode) {
++ int mode = S_IRWXU;
++ if (unlikely(au_is_nfs(plink->d_sb)))
++ mode |= S_IXUGO;
++ err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
++ } else if (S_ISDIR(plink->d_inode->i_mode))
++ err = 0;
++ else
++ Err("unknown %.*s exists\n", DLNPair(plink));
++
++ return err;
++}
++
++/*
++ * initialize the whiteout base file/dir for @br.
++ */
++int init_wh(struct dentry *h_root, struct aufs_branch *br,
++ struct vfsmount *nfsmnt, struct super_block *sb)
++{
++ int err;
++ struct dentry *wh, *plink;
++ struct inode *h_dir;
++ static struct qstr base_name[] = {
++ {.name = AUFS_WH_BASENAME, .len = sizeof(AUFS_WH_BASENAME) - 1},
++ {.name = AUFS_WH_PLINKDIR, .len = sizeof(AUFS_WH_PLINKDIR) - 1}
++ };
++ struct lkup_args lkup = {
++ .nfsmnt = nfsmnt,
++ .dlgt = 0 // always no dlgt
++ };
++ const int do_plink = au_flag_test(sb, AuFlag_PLINK);
++
++ LKTRTrace("nfsmnt %p\n", nfsmnt);
++ BrWhMustWriteLock(br);
++ SiMustWriteLock(sb);
++ h_dir = h_root->d_inode;
++ IMustLock(h_dir);
++
++ // doubly whiteouted
++ wh = lkup_wh(h_root, base_name + 0, &lkup);
++ //if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
++ err = PTR_ERR(wh);
++ if (IS_ERR(wh))
++ goto out;
++ DEBUG_ON(br->br_wh && br->br_wh != wh);
++
++ plink = lkup_wh(h_root, base_name + 1, &lkup);
++ err = PTR_ERR(plink);
++ if (IS_ERR(plink))
++ goto out_dput_wh;
++ DEBUG_ON(br->br_plink && br->br_plink != plink);
++
++ dput(br->br_wh);
++ dput(br->br_plink);
++ br->br_wh = br->br_plink = NULL;
++
++ err = 0;
++ switch (br->br_perm) {
++ case AuBr_RR:
++ case AuBr_RO:
++ case AuBr_RRWH:
++ case AuBr_ROWH:
++ clean_wh(h_dir, wh);
++ clean_plink(h_dir, plink);
++ break;
++
++ case AuBr_RWNoLinkWH:
++ clean_wh(h_dir, wh);
++ if (do_plink) {
++ err = test_linkable(h_dir);
++ if (unlikely(err))
++ goto out_nolink;
++
++ err = plink_dir(h_dir, plink);
++ if (unlikely(err))
++ goto out_err;
++ br->br_plink = dget(plink);
++ } else
++ clean_plink(h_dir, plink);
++ break;
++
++ case AuBr_RW:
++ /*
++ * for the moment, aufs supports the branch filesystem
++ * which does not support link(2).
++ * testing on FAT which does not support i_op->setattr() fully either,
++ * copyup failed.
++ * finally, such filesystem will not be used as the writable branch.
++ */
++ err = test_linkable(h_dir);
++ if (unlikely(err))
++ goto out_nolink;
++
++ err = -EEXIST;
++ if (!wh->d_inode)
++ err = vfsub_create(h_dir, wh, WH_MASK, NULL, /*dlgt*/0);
++ else if (S_ISREG(wh->d_inode->i_mode))
++ err = 0;
++ else
++ Err("unknown %.*s/%.*s exists\n",
++ DLNPair(h_root), DLNPair(wh));
++ if (unlikely(err))
++ goto out_err;
++
++ if (do_plink) {
++ err = plink_dir(h_dir, plink);
++ if (unlikely(err))
++ goto out_err;
++ br->br_plink = dget(plink);
++ } else
++ clean_plink(h_dir, plink);
++ br->br_wh = dget(wh);
++ break;
++
++ default:
++ BUG();
++ }
++
++ out_dput:
++ dput(plink);
++ out_dput_wh:
++ dput(wh);
++ out:
++ TraceErr(err);
++ return err;
++ out_nolink:
++ Err("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
++ DLNPair(h_root));
++ goto out_dput;
++ out_err:
++ Err("an error(%d) on the writable branch %.*s(%s)\n",
++ err, DLNPair(h_root), au_sbtype(h_root->d_sb));
++ goto out_dput;
++}
++
++struct reinit_br_wh {
++ struct super_block *sb;
++ struct aufs_branch *br;
++};
++
++static void reinit_br_wh(void *arg)
++{
++ int err;
++ struct reinit_br_wh *a = arg;
++ struct inode *hidden_dir, *dir;
++ struct dentry *hidden_root;
++ aufs_bindex_t bindex;
++
++ TraceEnter();
++ DEBUG_ON(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
++
++ err = 0;
++ /* big lock */
++ si_write_lock(a->sb);
++ if (unlikely(!br_writable(a->br->br_perm)))
++ goto out;
++ bindex = find_brindex(a->sb, a->br->br_id);
++ if (unlikely(bindex < 0))
++ goto out;
++
++ dir = a->sb->s_root->d_inode;
++ hidden_root = a->br->br_wh->d_parent;
++ hidden_dir = hidden_root->d_inode;
++ DEBUG_ON(!hidden_dir->i_op || !hidden_dir->i_op->link);
++ hdir_lock(hidden_dir, dir, bindex);
++ br_wh_write_lock(a->br);
++ err = vfsub_unlink(hidden_dir, a->br->br_wh, /*dlgt*/0);
++ //if (LktrCond) err = -1;
++ dput(a->br->br_wh);
++ a->br->br_wh = NULL;
++ if (!err)
++ err = init_wh(hidden_root, a->br, au_do_nfsmnt(a->br->br_mnt),
++ a->sb);
++ br_wh_write_unlock(a->br);
++ hdir_unlock(hidden_dir, dir, bindex);
++
++ out:
++ atomic_dec(&a->br->br_wh_running);
++ br_put(a->br);
++ si_write_unlock(a->sb);
++ au_mntput(a->sb);
++ kfree(arg);
++ if (unlikely(err))
++ IOErr("err %d\n", err);
++}
++
++static void kick_reinit_br_wh(struct super_block *sb, struct aufs_branch *br)
++{
++ int do_dec;
++ struct reinit_br_wh *arg;
++
++ do_dec = 1;
++ if (atomic_inc_return(&br->br_wh_running) != 1)
++ goto out;
++
++ // ignore ENOMEM
++ arg = kmalloc(sizeof(*arg), GFP_KERNEL);
++ if (arg) {
++ // dec(wh_running), kfree(arg) and br_put() in reinit function
++ arg->sb = sb;
++ arg->br = br;
++ br_get(br);
++ /* prohibit umount */
++ au_mntget(sb);
++ au_wkq_nowait(reinit_br_wh, arg, /*dlgt*/0);
++ do_dec = 0;
++ }
++
++ out:
++ if (do_dec)
++ atomic_dec(&br->br_wh_running);
++}
++
++/*
++ * create the whiteoute @wh.
++ */
++static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ int err, dlgt;
++ struct aufs_branch *br;
++ struct dentry *hidden_parent;
++ struct inode *hidden_dir;
++
++ LKTRTrace("%.*s\n", DLNPair(wh));
++ SiMustReadLock(sb);
++ hidden_parent = wh->d_parent;
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ dlgt = need_dlgt(sb);
++ br = stobr(sb, bindex);
++ br_wh_read_lock(br);
++ if (br->br_wh) {
++ err = vfsub_link(br->br_wh, hidden_dir, wh, dlgt);
++ if (!err || err != -EMLINK)
++ goto out;
++
++ // link count full. re-initialize br_wh.
++ kick_reinit_br_wh(sb, br);
++ }
++
++ // return this error in this context
++ err = vfsub_create(hidden_dir, wh, WH_MASK, NULL, dlgt);
++
++ out:
++ br_wh_read_unlock(br);
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create or remove the diropq.
++ */
++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt)
++{
++ struct dentry *opq_dentry, *hidden_dentry;
++ struct inode *hidden_dir;
++ int err;
++ struct super_block *sb;
++ struct lkup_args lkup;
++
++ LKTRTrace("%.*s, bindex %d, do_create %d\n", DLNPair(dentry),
++ bindex, do_create);
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ DEBUG_ON(!hidden_dentry);
++ hidden_dir = hidden_dentry->d_inode;
++ DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
++ IMustLock(hidden_dir);
++
++ // already checked by au_test_perm().
++ sb = dentry->d_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = dlgt;
++ opq_dentry = lkup_one(diropq_name.name, hidden_dentry, diropq_name.len,
++ &lkup);
++ //if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
++ if (IS_ERR(opq_dentry))
++ goto out;
++
++ if (do_create) {
++ DEBUG_ON(opq_dentry->d_inode);
++ err = link_or_create_wh(opq_dentry, sb, bindex);
++ //if (LktrCond) {vfs_unlink(hidden_dir, opq_dentry); err = -1;}
++ if (!err) {
++ set_dbdiropq(dentry, bindex);
++ goto out; /* success */
++ }
++ } else {
++ DEBUG_ON(/* !S_ISDIR(dentry->d_inode->i_mode)
++ * || */!opq_dentry->d_inode);
++ err = vfsub_unlink(hidden_dir, opq_dentry, lkup.dlgt);
++ //if (LktrCond) err = -1;
++ if (!err)
++ set_dbdiropq(dentry, -1);
++ }
++ dput(opq_dentry);
++ opq_dentry = ERR_PTR(err);
++
++ out:
++ TraceErrPtr(opq_dentry);
++ return opq_dentry;
++}
++
++struct do_diropq_args {
++ struct dentry **errp;
++ struct dentry *dentry;
++ aufs_bindex_t bindex;
++ int do_create, dlgt;
++};
++
++static void call_do_diropq(void *args)
++{
++ struct do_diropq_args *a = args;
++ *a->errp = do_diropq(a->dentry, a->bindex, a->do_create, a->dlgt);
++}
++
++struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt)
++{
++ struct dentry *diropq, *hidden_dentry;
++
++ LKTRTrace("%.*s, bindex %d, do_create %d\n",
++ DLNPair(dentry), bindex, do_create);
++
++ hidden_dentry = au_h_dptr_i(dentry, bindex);
++ if (!au_test_perm(hidden_dentry->d_inode, MAY_EXEC | MAY_WRITE, dlgt))
++ diropq = do_diropq(dentry, bindex, do_create, dlgt);
++ else {
++ struct do_diropq_args args = {
++ .errp = &diropq,
++ .dentry = dentry,
++ .bindex = bindex,
++ .do_create = do_create,
++ .dlgt = dlgt
++ };
++ au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
++ }
++
++ TraceErrPtr(diropq);
++ return diropq;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * lookup whiteout dentry.
++ * @hidden_parent: hidden parent dentry which must exist and be locked
++ * @base_name: name of dentry which will be whiteouted
++ * returns dentry for whiteout.
++ */
++struct dentry *lkup_wh(struct dentry *hidden_parent, struct qstr *base_name,
++ struct lkup_args *lkup)
++{
++ int err;
++ struct qstr wh_name;
++ struct dentry *wh_dentry;
++
++ LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(base_name));
++ IMustLock(hidden_parent->d_inode);
++
++ err = au_alloc_whname(base_name->name, base_name->len, &wh_name);
++ //if (LktrCond) {au_free_whname(&wh_name); err = -1;}
++ wh_dentry = ERR_PTR(err);
++ if (!err) {
++ // do not superio.
++ wh_dentry = lkup_one(wh_name.name, hidden_parent, wh_name.len,
++ lkup);
++ au_free_whname(&wh_name);
++ }
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/*
++ * link/create a whiteout for @dentry on @bindex.
++ */
++struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *hidden_parent,
++ struct lkup_args *lkup)
++{
++ struct dentry *wh_dentry;
++ int err;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s/%.*s on b%d\n", DLNPair(hidden_parent),
++ DLNPair(dentry), bindex);
++
++ sb = dentry->d_sb;
++ wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, lkup);
++ //au_nfsmnt(sb, bindex), need_dlgt(sb));
++ //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
++ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
++ IMustLock(hidden_parent->d_inode);
++ err = link_or_create_wh(wh_dentry, sb, bindex);
++ if (!err)
++ set_dbwh(dentry, bindex);
++ else {
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(err);
++ }
++ }
++
++ TraceErrPtr(wh_dentry);
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Delete all whiteouts in this directory in branch bindex. */
++static int del_wh_children(struct aufs_nhash *whlist,
++ struct dentry *hidden_parent, aufs_bindex_t bindex,
++ struct lkup_args *lkup)
++{
++ int err, i;
++ struct qstr wh_name;
++ char *p;
++ struct inode *hidden_dir;
++ struct hlist_head *head;
++ struct aufs_wh *tpos;
++ struct hlist_node *pos;
++ struct aufs_destr *str;
++
++ LKTRTrace("%.*s\n", DLNPair(hidden_parent));
++ hidden_dir = hidden_parent->d_inode;
++ IMustLock(hidden_dir);
++ DEBUG_ON(IS_RDONLY(hidden_dir));
++ //SiMustReadLock(??);
++
++ err = -ENOMEM;
++ wh_name.name = p = __getname();
++ //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
++ if (unlikely(!wh_name.name))
++ goto out;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++
++ // already checked by au_test_perm().
++ err = 0;
++ for (i = 0; !err && i < AUFS_NHASH_SIZE; i++) {
++ head = whlist->heads + i;
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ if (tpos->wh_bindex != bindex)
++ continue;
++ str = &tpos->wh_str;
++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
++ memcpy(p, str->name, str->len);
++ wh_name.len = AUFS_WH_PFX_LEN + str->len;
++ err = unlink_wh_name(hidden_parent, &wh_name,
++ lkup);
++ //if (LktrCond) err = -1;
++ if (!err)
++ continue;
++ break;
++ }
++ IOErr("whiteout name too long %.*s\n",
++ str->len, str->name);
++ err = -EIO;
++ break;
++ }
++ }
++ __putname(wh_name.name);
++
++ out:
++ TraceErr(err);
++ return err;
++}
++
++struct del_wh_children_args {
++ int *errp;
++ struct aufs_nhash *whlist;
++ struct dentry *hidden_parent;
++ aufs_bindex_t bindex;
++ struct lkup_args *lkup;
++};
++
++static void call_del_wh_children(void *args)
++{
++ struct del_wh_children_args *a = args;
++ *a->errp = del_wh_children(a->whlist, a->hidden_parent, a->bindex,
++ a->lkup);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * rmdir the whiteouted temporary named dir @hidden_dentry.
++ * @whlist: whiteouted children.
++ */
++int rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir, struct inode *inode)
++{
++ int err;
++ struct inode *hidden_inode, *hidden_dir;
++ struct lkup_args lkup;
++ struct super_block *sb;
++
++ LKTRTrace("hd %.*s, b%d, i%lu\n",
++ DLNPair(hidden_dentry), bindex, dir->i_ino);
++ IMustLock(dir);
++ IiMustAnyLock(dir);
++ hidden_dir = hidden_dentry->d_parent->d_inode;
++ IMustLock(hidden_dir);
++
++ sb = inode->i_sb;
++ lkup.nfsmnt = au_nfsmnt(sb, bindex);
++ lkup.dlgt = need_dlgt(sb);
++ hidden_inode = hidden_dentry->d_inode;
++ DEBUG_ON(hidden_inode != au_h_iptr_i(inode, bindex));
++ hdir2_lock(hidden_inode, inode, bindex);
++ if (!au_test_perm(hidden_inode, MAY_EXEC | MAY_WRITE, lkup.dlgt))
++ err = del_wh_children(whlist, hidden_dentry, bindex, &lkup);
++ else {
++ // ugly
++ int dlgt = lkup.dlgt;
++ struct del_wh_children_args args = {
++ .errp = &err,
++ .whlist = whlist,
++ .hidden_parent = hidden_dentry,
++ .bindex = bindex,
++ .lkup = &lkup
++ };
++
++ lkup.dlgt = 0;
++ au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
++ lkup.dlgt = dlgt;
++ }
++ hdir_unlock(hidden_inode, inode, bindex);
++
++ if (!err) {
++ err = vfsub_rmdir(hidden_dir, hidden_dentry, lkup.dlgt);
++ //d_drop(hidden_dentry);
++ //if (LktrCond) err = -1;
++ }
++
++ if (!err) {
++ if (ibstart(dir) == bindex) {
++ au_cpup_attr_timesizes(dir);
++ //au_cpup_attr_nlink(dir);
++ dir->i_nlink--;
++ }
++ return 0; /* success */
++ }
++
++ Warn("failed removing %.*s(%d), ignored\n",
++ DLNPair(hidden_dentry), err);
++ return err;
++}
++
++static void do_rmdir_whtmp(void *arg)
++{
++ int err;
++ struct rmdir_whtmp_arg *a = arg;
++ struct super_block *sb;
++
++ LKTRTrace("%.*s, b%d, dir i%lu\n",
++ DLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
++
++ i_lock(a->dir);
++ sb = a->dir->i_sb;
++ si_read_lock(sb);
++ err = test_ro(sb, a->bindex, NULL);
++ if (!err) {
++ struct inode *hidden_dir = a->h_dentry->d_parent->d_inode;
++
++ ii_write_lock_child(a->inode);
++ ii_write_lock_parent(a->dir);
++ hdir_lock(hidden_dir, a->dir, a->bindex);
++ err = rmdir_whtmp(a->h_dentry, &a->whlist, a->bindex,
++ a->dir, a->inode);
++ hdir_unlock(hidden_dir, a->dir, a->bindex);
++ ii_write_unlock(a->dir);
++ ii_write_unlock(a->inode);
++ }
++ dput(a->h_dentry);
++ nhash_fin(&a->whlist);
++ iput(a->inode);
++ si_read_unlock(sb);
++ au_mntput(sb);
++ i_unlock(a->dir);
++ iput(a->dir);
++ kfree(arg);
++ if (unlikely(err))
++ IOErr("err %d\n", err);
++}
++
++void kick_rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir,
++ struct inode *inode, struct rmdir_whtmp_arg *arg)
++{
++ LKTRTrace("%.*s\n", DLNPair(hidden_dentry));
++ IMustLock(dir);
++
++ // all post-process will be done in do_rmdir_whtmp().
++ arg->h_dentry = dget(hidden_dentry);
++ nhash_init(&arg->whlist);
++ nhash_move(&arg->whlist, whlist);
++ arg->bindex = bindex;
++ arg->dir = igrab(dir);
++ arg->inode = igrab(inode);
++ /* prohibit umount */
++ au_mntget(dir->i_sb);
++
++ au_wkq_nowait(do_rmdir_whtmp, arg, /*dlgt*/0);
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/whout.h linux-2.6.22.1/fs/aufs/whout.h
+--- linux-2.6.22.1.oorig/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/whout.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: whout.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
++
++#ifndef __AUFS_WHOUT_H__
++#define __AUFS_WHOUT_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++
++int au_alloc_whname(const char *name, int len, struct qstr *wh);
++void au_free_whname(struct qstr *wh);
++
++struct lkup_args;
++int is_wh(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
++ struct lkup_args *lkup);
++int is_diropq(struct dentry *h_dentry, struct lkup_args *lkup);
++
++struct dentry *lkup_whtmp(struct dentry *h_parent, struct qstr *prefix,
++ struct lkup_args *lkup);
++int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex);
++int au_unlink_wh_dentry(struct inode *h_dir, struct dentry *wh_dentry,
++ struct dentry *dentry, int dlgt);
++
++struct aufs_branch;
++int init_wh(struct dentry *h_parent, struct aufs_branch *br,
++ struct vfsmount *nfsmnt, struct super_block *sb);
++
++struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int do_create, int dlgt);
++
++struct dentry *lkup_wh(struct dentry *h_parent, struct qstr *base_name,
++ struct lkup_args *lkup);
++struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent,
++ struct lkup_args *lkup);
++
++/* real rmdir the whiteout-ed dir */
++struct rmdir_whtmp_arg {
++ struct dentry *h_dentry;
++ struct aufs_nhash whlist;
++ aufs_bindex_t bindex;
++ struct inode *dir, *inode;
++};
++
++struct aufs_nhash;
++int rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir, struct inode *inode);
++void kick_rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
++ aufs_bindex_t bindex, struct inode *dir,
++ struct inode *inode, struct rmdir_whtmp_arg *arg);
++
++/* ---------------------------------------------------------------------- */
++
++static inline
++struct dentry *create_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ int dlgt)
++{
++ return sio_diropq(dentry, bindex, 1, dlgt);
++}
++
++static inline
++int remove_diropq(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
++{
++ return PTR_ERR(sio_diropq(dentry, bindex, 0, dlgt));
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WHOUT_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/wkq.c linux-2.6.22.1/fs/aufs/wkq.c
+--- linux-2.6.22.1.oorig/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/wkq.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,283 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: wkq.c,v 1.14 2007/05/14 03:39:10 sfjro Exp $ */
++
++#include <linux/module.h>
++#include "aufs.h"
++
++struct au_wkq *au_wkq;
++
++struct au_cred {
++#ifdef CONFIG_AUFS_DLGT
++ uid_t fsuid;
++ gid_t fsgid;
++ kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
++ //unsigned keep_capabilities:1;
++ //struct user_struct *user;
++ //struct fs_struct *fs;
++ //struct nsproxy *nsproxy;
++#endif
++};
++
++struct au_wkinfo {
++ struct work_struct wk;
++
++ unsigned int wait:1;
++ unsigned int dlgt:1;
++ struct au_cred cred;
++
++ au_wkq_func_t func;
++ void *args;
++
++ atomic_t *busyp;
++ struct completion *comp;
++};
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_DLGT
++static void cred_store(struct au_cred *cred)
++{
++ cred->fsuid = current->fsuid;
++ cred->fsgid = current->fsgid;
++ cred->cap_effective = current->cap_effective;
++ cred->cap_inheritable = current->cap_inheritable;
++ cred->cap_permitted = current->cap_permitted;
++}
++
++static void cred_revert(struct au_cred *cred)
++{
++ DEBUG_ON(!is_au_wkq(current));
++ current->fsuid = cred->fsuid;
++ current->fsgid = cred->fsgid;
++ current->cap_effective = cred->cap_effective;
++ current->cap_inheritable = cred->cap_inheritable;
++ current->cap_permitted = cred->cap_permitted;
++}
++
++static void cred_switch(struct au_cred *old, struct au_cred *new)
++{
++ cred_store(old);
++ cred_revert(new);
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++#ifdef CONFIG_AUFS_SYSAUFS
++ unsigned int new, old;
++
++ do {
++ new = atomic_read(wkinfo->busyp);
++ old = wkq->max_busy;
++ if (new <= old)
++ break;
++ } while (cmpxchg(&wkq->max_busy, old, new) == old);
++#endif
++}
++
++static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++ wkinfo->busyp = &wkq->busy;
++ update_busy(wkq, wkinfo);
++ if (wkinfo->wait)
++ return !queue_work(wkq->q, &wkinfo->wk);
++ else
++ return !schedule_work(&wkinfo->wk);
++}
++
++static void do_wkq(struct au_wkinfo *wkinfo)
++{
++ unsigned int idle, n;
++ int i, idle_idx;
++
++ TraceEnter();
++
++ while (1) {
++ if (wkinfo->wait) {
++ idle_idx = 0;
++ idle = UINT_MAX;
++ for (i = 0; i < aufs_nwkq; i++) {
++ n = atomic_inc_return(&au_wkq[i].busy);
++ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
++ return; /* success */
++
++ if (n < idle) {
++ idle_idx = i;
++ idle = n;
++ }
++ atomic_dec(&au_wkq[i].busy);
++ }
++ } else
++ idle_idx = aufs_nwkq;
++
++ atomic_inc(&au_wkq[idle_idx].busy);
++ if (!enqueue(au_wkq + idle_idx, wkinfo))
++ return; /* success */
++
++ /* impossible? */
++ Warn1("failed to queue_work()\n");
++ yield();
++ }
++}
++
++static AuWkqFunc(wkq_func, wk)
++{
++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
++
++ LKTRTrace("wkinfo{%u, %u, %p, %p, %p}\n",
++ wkinfo->wait, wkinfo->dlgt, wkinfo->func, wkinfo->busyp,
++ wkinfo->comp);
++#ifdef CONFIG_AUFS_DLGT
++ if (!wkinfo->dlgt)
++ wkinfo->func(wkinfo->args);
++ else {
++ struct au_cred cred;
++ cred_switch(&cred, &wkinfo->cred);
++ wkinfo->func(wkinfo->args);
++ cred_revert(&cred);
++ }
++#else
++ wkinfo->func(wkinfo->args);
++#endif
++ atomic_dec(wkinfo->busyp);
++ if (wkinfo->wait)
++ complete(wkinfo->comp);
++ else {
++ kfree(wkinfo);
++ module_put(THIS_MODULE);
++ }
++}
++
++void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait)
++{
++ DECLARE_COMPLETION_ONSTACK(comp);
++ struct au_wkinfo _wkinfo = {
++ .wait = 1,
++ .dlgt = !!dlgt,
++ .func = func,
++ .args = args,
++ .comp = &comp
++ }, *wkinfo = &_wkinfo;
++
++ LKTRTrace("dlgt %d, do_wait %d\n", dlgt, do_wait);
++ DEBUG_ON(is_au_wkq(current));
++
++ if (unlikely(!do_wait)) {
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ /*
++ * never fail.
++ * wkq_func() must free this wkinfo.
++ * it highly depends upon the implementation of workqueue.
++ */
++ wait_event(wq, (wkinfo = kmalloc(sizeof(*wkinfo), GFP_KERNEL)));
++ wkinfo->wait = 0;
++ wkinfo->dlgt = !!dlgt;
++ wkinfo->func = func;
++ wkinfo->args = args;
++ wkinfo->comp = NULL;
++ __module_get(THIS_MODULE);
++ }
++
++ AuInitWkq(&wkinfo->wk, wkq_func);
++#ifdef CONFIG_AUFS_DLGT
++ if (dlgt)
++ cred_store(&wkinfo->cred);
++#endif
++ do_wkq(wkinfo);
++ if (do_wait)
++ wait_for_completion(wkinfo->comp);
++}
++
++#if 0
++void au_wkq_wait_nwtask(void)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ wait_event(wq, !atomic_read(&au_wkq[aufs_nwkq].busy));
++}
++#endif
++
++void au_wkq_fin(void)
++{
++ int i;
++
++ TraceEnter();
++
++ for (i = 0; i < aufs_nwkq; i++)
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
++ destroy_workqueue(au_wkq[i].q);
++ kfree(au_wkq);
++}
++
++int __init au_wkq_init(void)
++{
++ int err, i;
++ struct au_wkq *nowaitq;
++
++ LKTRTrace("%d\n", aufs_nwkq);
++
++ /* '+1' is for accounting of nowait queue */
++ err = -ENOMEM;
++ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
++ if (unlikely(!au_wkq))
++ goto out;
++
++ err = 0;
++ for (i = 0; i < aufs_nwkq; i++) {
++ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
++ atomic_set(&au_wkq[i].busy, 0);
++ au_wkq[i].max_busy = 0;
++ continue;
++ }
++
++ err = PTR_ERR(au_wkq[i].q);
++ au_wkq_fin();
++ break;
++ }
++
++ /* nowait accounting */
++ nowaitq = au_wkq + aufs_nwkq;
++ atomic_set(&nowaitq->busy, 0);
++ nowaitq->max_busy = 0;
++ nowaitq->q = NULL;
++
++#if 0 // test accouting
++ if (!err) {
++ static void f(void *args) {
++ DbgSleep(1);
++ }
++ int i;
++ //au_debug_on();
++ LKTRTrace("f %p\n", f);
++ for (i = 0; i < 10; i++)
++ au_wkq_nowait(f, NULL, 0);
++ for (i = 0; i < aufs_nwkq; i++)
++ au_wkq_wait(f, NULL, 0);
++ DbgSleep(11);
++ //au_debug_off();
++ }
++#endif
++
++ out:
++ TraceErr(err);
++ return err;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/wkq.h linux-2.6.22.1/fs/aufs/wkq.h
+--- linux-2.6.22.1.oorig/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/wkq.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: wkq.h,v 1.9 2007/05/14 03:39:10 sfjro Exp $ */
++
++#ifndef __AUFS_WKQ_H__
++#define __AUFS_WKQ_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sched.h>
++#include <linux/version.h>
++#include <linux/workqueue.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* internal workqueue named AUFS_WKQ_NAME */
++struct au_wkq {
++ struct workqueue_struct *q;
++
++ /* accounting */
++ atomic_t busy;
++ unsigned int max_busy;
++} ;//__attribute__ ((aligned));
++
++typedef void (*au_wkq_func_t)(void *args);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++#define AuInitWkq(wk, func) INIT_WORK(wk, func)
++#define AuWkqFunc(name, arg) void name(struct work_struct *arg)
++#else
++typedef void (*work_func_t)(void *arg);
++#define AuInitWkq(wk, func) INIT_WORK(wk, func, wk)
++#define AuWkqFunc(name, arg) void name(void *arg)
++#endif
++
++extern struct au_wkq *au_wkq;
++
++void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait);
++//void au_wkq_wait_nwtask(void);
++int __init au_wkq_init(void);
++void au_wkq_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int is_au_wkq(struct task_struct *tsk)
++{
++ return (!tsk->mm && !strcmp(current->comm, AUFS_WKQ_NAME));
++}
++
++static inline void au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
++{
++ au_wkq_run(func, args, dlgt, /*do_wait*/1);
++}
++
++static inline void au_wkq_nowait(au_wkq_func_t func, void *args, int dlgt)
++{
++ au_wkq_run(func, args, dlgt, /*do_wait*/0);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WKQ_H__ */
+diff -rduNp linux-2.6.22.1.oorig/fs/aufs/xino.c linux-2.6.22.1/fs/aufs/xino.c
+--- linux-2.6.22.1.oorig/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/aufs/xino.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,644 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: xino.c,v 1.27 2007/05/14 03:39:10 sfjro Exp $ */
++
++//#include <linux/fs.h>
++#include <linux/fsnotify.h>
++#include <asm/uaccess.h>
++#include "aufs.h"
++
++static readf_t find_readf(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->read)
++ return fop->read;
++ if (fop->aio_read)
++ return do_sync_read;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++static writef_t find_writef(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->write)
++ return fop->write;
++ if (fop->aio_write)
++ return do_sync_write;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t xino_fread(readf_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)size, *pos);
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ err = func(file, (char __user*)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++
++#if 0
++ if (err > 0)
++ fsnotify_access(file->f_dentry);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t do_xino_fwrite(writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ lockdep_off();
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ err = func(file, (const char __user*)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++ lockdep_on();
++
++#if 0
++ if (err > 0)
++ fsnotify_modify(file->f_dentry);
++#endif
++
++ TraceErr(err);
++ return err;
++}
++
++struct do_xino_fwrite_args {
++ ssize_t *errp;
++ writef_t func;
++ struct file *file;
++ void *buf;
++ size_t size;
++ loff_t *pos;
++};
++
++static void call_do_xino_fwrite(void *args)
++{
++ struct do_xino_fwrite_args *a = args;
++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
++}
++
++static ssize_t xino_fwrite(writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++
++ LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
++ DLNPair(file->f_dentry), (unsigned long)size, *pos);
++
++ // signal block and no wkq?
++ /*
++ * it breaks RLIMIT_FSIZE and normal user's limit,
++ * users should care about quota and real 'filesystem full.'
++ */
++ if (!is_au_wkq(current)) {
++ struct do_xino_fwrite_args args = {
++ .errp = &err,
++ .func = func,
++ .file = file,
++ .buf = buf,
++ .size = size,
++ .pos = pos
++ };
++ au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
++ } else
++ err = do_xino_fwrite(func, file, buf, size, pos);
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * write @ino to the xinofile for the specified branch{@sb, @bindex}
++ * at the position of @_ino.
++ * when @ino is zero, it is written to the xinofile and means no entry.
++ */
++int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino)
++{
++ struct aufs_branch *br;
++ loff_t pos;
++ ssize_t sz;
++
++ LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, xino->ino);
++ //DEBUG_ON(!xino->ino /* || !xino->h_gen */);
++ //WARN_ON(bindex == 0 && h_ino == 31);
++
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ return 0;
++
++ br = stobr(sb, bindex);
++ DEBUG_ON(!br || !br->br_xino);
++ pos = h_ino * sizeof(*xino);
++ sz = xino_fwrite(br->br_xino_write, br->br_xino, xino, sizeof(*xino),
++ &pos);
++ //if (LktrCond) sz = 1;
++ if (sz == sizeof(*xino))
++ return 0; /* success */
++
++ IOErr("write failed (%ld)\n", (long)sz);
++ return -EIO;
++}
++
++int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino)
++{
++ struct xino xino = {
++ .ino = 0
++ };
++ return xino_write(sb, bindex, h_ino, &xino);
++}
++
++// why is not atomic_long_inc_return defined?
++static DEFINE_SPINLOCK(alir_lock);
++static long atomic_long_inc_return(atomic_long_t *a)
++{
++ long l;
++
++ spin_lock(&alir_lock);
++ atomic_long_inc(a);
++ l = atomic_long_read(a);
++ spin_unlock(&alir_lock);
++ return l;
++}
++
++ino_t xino_new_ino(struct super_block *sb)
++{
++ ino_t ino;
++
++ TraceEnter();
++ ino = atomic_long_inc_return(&stosi(sb)->si_xino);
++ BUILD_BUG_ON(AUFS_FIRST_INO < AUFS_ROOT_INO);
++ if (ino >= AUFS_ROOT_INO)
++ return ino;
++ else {
++ atomic_long_dec(&stosi(sb)->si_xino);
++ IOErr1("inode number overflow\n");
++ return 0;
++ }
++}
++
++/*
++ * read @ino from xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * if @ino does not exist and @do_new is true, get new one.
++ */
++int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ struct xino *xino)
++{
++ int err;
++ struct aufs_branch *br;
++ struct file *file;
++ loff_t pos;
++ ssize_t sz;
++
++ LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
++
++ err = 0;
++ xino->ino = 0;
++ if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
++ return 0; /* no ino */
++
++ br = stobr(sb, bindex);
++ file = br->br_xino;
++ DEBUG_ON(!file);
++ pos = h_ino * sizeof(*xino);
++ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xino))
++ return 0; /* no ino */
++
++ sz = xino_fread(br->br_xino_read, file, xino, sizeof(*xino), &pos);
++ if (sz == sizeof(*xino))
++ return 0; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ IOErr("xino read error (%ld)\n", (long)sz);
++ }
++
++ TraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct file *xino_create(struct super_block *sb, char *fname, int silent,
++ struct dentry *parent)
++{
++ struct file *file;
++ int err;
++ struct dentry *hidden_parent;
++ struct inode *hidden_dir;
++ //const int udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
++
++ LKTRTrace("%s\n", fname);
++ //DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++
++ // LSM may detect it
++ // use sio?
++ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ S_IRUGO | S_IWUGO);
++ //file = ERR_PTR(-1);
++ if (IS_ERR(file)) {
++ if (!silent)
++ Err("open %s(%ld)\n", fname, PTR_ERR(file));
++ return file;
++ }
++#if 0
++ if (unlikely(udba && parent))
++ au_direval_dec(parent);
++#endif
++
++ /* keep file count */
++ hidden_parent = dget_parent(file->f_dentry);
++ hidden_dir = hidden_parent->d_inode;
++ hi_lock_parent(hidden_dir);
++ err = vfsub_unlink(hidden_dir, file->f_dentry, /*dlgt*/0);
++#if 0
++ if (unlikely(!err && udba && parent))
++ au_direval_dec(parent);
++#endif
++ i_unlock(hidden_dir);
++ dput(hidden_parent);
++ if (unlikely(err)) {
++ if (!silent)
++ Err("unlink %s(%d)\n", fname, err);
++ goto out;
++ }
++ if (sb != file->f_dentry->d_sb)
++ return file; /* success */
++
++ if (!silent)
++ Err("%s must be outside\n", fname);
++ err = -EINVAL;
++
++ out:
++ fput(file);
++ file = ERR_PTR(err);
++ return file;
++}
++
++/*
++ * find another branch who is on the same filesystem of the specified
++ * branch{@btgt}. search until @bend.
++ */
++static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
++ aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++ struct super_block *tgt_sb = sbr_sb(sb, btgt);
++
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(btgt != bindex && tgt_sb == sbr_sb(sb, bindex)))
++ return bindex;
++ return -1;
++}
++
++/*
++ * create a new xinofile at the same place/path as @base_file.
++ */
++static struct file *xino_create2(struct file *base_file)
++{
++ struct file *file;
++ int err;
++ struct dentry *base, *dentry, *parent;
++ struct inode *dir;
++ struct qstr *name;
++ struct lkup_args lkup = {
++ .nfsmnt = NULL,
++ .dlgt = 0
++ };
++
++ base = base_file->f_dentry;
++ LKTRTrace("%.*s\n", DLNPair(base));
++ parent = dget_parent(base);
++ dir = parent->d_inode;
++ IMustLock(dir);
++
++ file = ERR_PTR(-EINVAL);
++ if (unlikely(au_is_nfs(parent->d_sb)))
++ goto out;
++
++ // do not superio, nor NFS.
++ name = &base->d_name;
++ dentry = lkup_one(name->name, parent, name->len, &lkup);
++ //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
++ if (IS_ERR(dentry)) {
++ file = (void*)dentry;
++ Err("%.*s lookup err %ld\n", LNPair(name), PTR_ERR(dentry));
++ goto out;
++ }
++ err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, /*dlgt*/0);
++ //if (LktrCond) {vfs_unlink(dir, dentry); err = -1;}
++ if (unlikely(err)) {
++ file = ERR_PTR(err);
++ Err("%.*s create err %d\n", LNPair(name), err);
++ goto out_dput;
++ }
++ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ if (IS_ERR(file)) {
++ Err("%.*s open err %ld\n", LNPair(name), PTR_ERR(file));
++ goto out_dput;
++ }
++ err = vfsub_unlink(dir, dentry, /*dlgt*/0);
++ //if (LktrCond) err = -1;
++ if (!err)
++ goto out_dput; /* success */
++
++ Err("%.*s unlink err %d\n", LNPair(name), err);
++ fput(file);
++ file = ERR_PTR(err);
++
++ out_dput:
++ dput(dentry);
++ out:
++ dput(parent);
++ TraceErrPtr(file);
++ return file;
++}
++
++/*
++ * initialize the xinofile for the specified branch{@sb, @bindex}
++ * at the place/path where @base_file indicates.
++ * test whether another branch is on the same filesystem or not,
++ * if @do_test is true.
++ */
++int xino_init(struct super_block *sb, aufs_bindex_t bindex,
++ struct file *base_file, int do_test)
++{
++ int err;
++ struct aufs_branch *br;
++ aufs_bindex_t bshared, bend;
++ struct file *file;
++ struct inode *inode, *hidden_inode;
++ struct xino xino;
++
++ LKTRTrace("b%d, base_file %p, do_test %d\n",
++ bindex, base_file, do_test);
++ SiMustWriteLock(sb);
++ DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
++ br = stobr(sb, bindex);
++ DEBUG_ON(br->br_xino);
++
++ file = NULL;
++ bshared = -1;
++ bend = sbend(sb);
++ if (do_test)
++ bshared = is_sb_shared(sb, bindex, bend);
++ if (unlikely(bshared >= 0)) {
++ struct aufs_branch *shared_br = stobr(sb, bshared);
++ if (shared_br->br_xino) {
++ file = shared_br->br_xino;
++ get_file(file);
++ }
++ }
++
++ if (!file) {
++ struct dentry *parent = dget_parent(base_file->f_dentry);
++ struct inode *dir = parent->d_inode;
++
++ hi_lock_parent(dir);
++ file = xino_create2(base_file);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ i_unlock(dir);
++ dput(parent);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ }
++ br->br_xino_read = find_readf(file);
++ err = PTR_ERR(br->br_xino_read);
++ if (IS_ERR(br->br_xino_read))
++ goto out_put;
++ br->br_xino_write = find_writef(file);
++ err = PTR_ERR(br->br_xino_write);
++ if (IS_ERR(br->br_xino_write))
++ goto out_put;
++ br->br_xino = file;
++
++ inode = sb->s_root->d_inode;
++ hidden_inode = au_h_iptr_i(inode, bindex);
++ xino.ino = inode->i_ino;
++ //xino.h_gen = hidden_inode->i_generation;
++ //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
++ err = xino_write(sb, bindex, hidden_inode->i_ino, &xino);
++ //if (LktrCond) err = -1;
++ if (!err)
++ return 0; /* success */
++
++ br->br_xino = NULL;
++
++ out_put:
++ fput(file);
++ out:
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * set xino mount option.
++ */
++int xino_set(struct super_block *sb, struct opt_xino *xino, int remount)
++{
++ int err, sparse;
++ aufs_bindex_t bindex, bend;
++ struct aufs_branch *br;
++ struct dentry *parent;
++ struct qstr *name;
++ struct file *cur_xino;
++ struct inode *dir;
++
++ LKTRTrace("%s\n", xino->path);
++
++ err = 0;
++ name = &xino->file->f_dentry->d_name;
++ parent = dget_parent(xino->file->f_dentry);
++ dir = parent->d_inode;
++ cur_xino = stobr(sb, 0)->br_xino;
++ if (remount
++ && cur_xino
++ && cur_xino->f_dentry->d_parent == parent
++ && name->len == cur_xino->f_dentry->d_name.len
++ && !memcmp(name->name, cur_xino->f_dentry->d_name.name, name->len))
++ goto out;
++
++ au_flag_set(sb, AuFlag_XINO);
++ bend = sbend(sb);
++ for (bindex = bend; bindex >= 0; bindex--) {
++ br = stobr(sb, bindex);
++ if (unlikely(br->br_xino && file_count(br->br_xino) > 1)) {
++ fput(br->br_xino);
++ br->br_xino = NULL;
++ }
++ }
++
++ for (bindex = 0; bindex <= bend; bindex++) {
++ struct file *file;
++ struct inode *inode;
++
++ br = stobr(sb, bindex);
++ if (unlikely(!br->br_xino))
++ continue;
++
++ DEBUG_ON(file_count(br->br_xino) != 1);
++ hi_lock_parent(dir);
++ file = xino_create2(xino->file);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ err = PTR_ERR(file);
++ if (IS_ERR(file)) {
++ i_unlock(dir);
++ break;
++ }
++ inode = br->br_xino->f_dentry->d_inode;
++ err = au_copy_file(file, br->br_xino, i_size_read(inode), sb,
++ &sparse);
++ //if (LktrCond) err = -1;
++ i_unlock(dir);
++ if (unlikely(err)) {
++ fput(file);
++ break;
++ }
++ fput(br->br_xino);
++ br->br_xino = file;
++ br->br_xino_read = find_readf(file);
++ DEBUG_ON(IS_ERR(br->br_xino_read));
++ br->br_xino_write = find_writef(file);
++ DEBUG_ON(IS_ERR(br->br_xino_write));
++ }
++
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(!stobr(sb, bindex)->br_xino)) {
++ err = xino_init(sb, bindex, xino->file, /*do_test*/1);
++ //if (LktrCond) {fput(stobr(sb, bindex)->br_xino);
++ //stobr(sb, bindex)->br_xino = NULL; err = -1;}
++ if (!err)
++ continue;
++ IOErr("creating xino for branch %d(%d), "
++ "forcing noxino\n", bindex, err);
++ err = -EIO;
++ break;
++ }
++ out:
++ dput(parent);
++ if (!err)
++ au_flag_set(sb, AuFlag_XINO);
++ else
++ au_flag_clr(sb, AuFlag_XINO);
++ TraceErr(err);
++ return err;
++}
++
++/*
++ * clear xino mount option
++ */
++int xino_clr(struct super_block *sb)
++{
++ aufs_bindex_t bindex, bend;
++
++ TraceEnter();
++ SiMustWriteLock(sb);
++
++ bend = sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ struct aufs_branch *br;
++ br = stobr(sb, bindex);
++ if (br->br_xino) {
++ fput(br->br_xino);
++ br->br_xino = NULL;
++ }
++ }
++
++ //todo: need to make iunique() to return the larger inode number
++
++ au_flag_clr(sb, AuFlag_XINO);
++ return 0;
++}
++
++/*
++ * create a xinofile at the default place/path.
++ */
++struct file *xino_def(struct super_block *sb)
++{
++ struct file *file;
++ aufs_bindex_t bend, bindex, bwr;
++ char *page, *p;
++
++ bend = sbend(sb);
++ bwr = -1;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (br_writable(sbr_perm(sb, bindex))
++ && !au_is_nfs(au_h_dptr_i(sb->s_root, bindex)->d_sb)) {
++ bwr = bindex;
++ break;
++ }
++
++ if (bwr != -1) {
++ // todo: rewrite with lkup_one()
++ file = ERR_PTR(-ENOMEM);
++ page = __getname();
++ //if (LktrCond) {__putname(page); page = NULL;}
++ if (unlikely(!page))
++ goto out;
++ p = d_path(au_h_dptr_i(sb->s_root, bwr), sbr_mnt(sb, bwr), page,
++ PATH_MAX - sizeof(AUFS_XINO_FNAME));
++ //if (LktrCond) p = ERR_PTR(-1);
++ file = (void*)p;
++ if (p && !IS_ERR(p)) {
++ strcat(p, "/" AUFS_XINO_FNAME);
++ LKTRTrace("%s\n", p);
++ file = xino_create(sb, p, /*silent*/0, sb->s_root);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ }
++ __putname(page);
++ } else {
++ file = xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
++ /*parent*/NULL);
++ //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
++ }
++
++ out:
++ TraceErrPtr(file);
++ return file;
++}
+diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/Makefile linux-2.6.22.1/fs/squashfs/Makefile
+--- linux-2.6.22.1.oorig/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/squashfs/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,7 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++obj-$(CONFIG_SQUASHFS) += squashfs.o
++squashfs-y += inode.o
++squashfs-y += squashfs2_0.o
+diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/inode.c linux-2.6.22.1/fs/squashfs/inode.c
+--- linux-2.6.22.1.oorig/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/squashfs/inode.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,2329 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/zlib.h>
++#include <linux/fs.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/vmalloc.h>
++#include <linux/smp_lock.h>
++
++#include "squashfs.h"
++
++static void vfs_read_inode(struct inode *i);
++static struct dentry *squashfs_get_parent(struct dentry *child);
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
++static int squashfs_statfs(struct dentry *, struct kstatfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
++ struct nameidata *);
++static int squashfs_remount(struct super_block *s, int *flags, char *data);
++static void squashfs_put_super(struct super_block *);
++static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
++ struct vfsmount *);
++static struct inode *squashfs_alloc_inode(struct super_block *sb);
++static void squashfs_destroy_inode(struct inode *inode);
++static int init_inodecache(void);
++static void destroy_inodecache(void);
++
++static struct file_system_type squashfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "squashfs",
++ .get_sb = squashfs_get_sb,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV
++};
++
++static const unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_super_ops = {
++ .alloc_inode = squashfs_alloc_inode,
++ .destroy_inode = squashfs_destroy_inode,
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++ .remount_fs = squashfs_remount
++};
++
++static struct super_operations squashfs_export_super_ops = {
++ .alloc_inode = squashfs_alloc_inode,
++ .destroy_inode = squashfs_destroy_inode,
++ .statfs = squashfs_statfs,
++ .put_super = squashfs_put_super,
++ .read_inode = vfs_read_inode
++};
++
++static struct export_operations squashfs_export_ops = {
++ .get_parent = squashfs_get_parent
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
++ .readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_aops = {
++ .readpage = squashfs_readpage
++};
++
++SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
++ .readpage = squashfs_readpage4K
++};
++
++static const struct file_operations squashfs_dir_ops = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir
++};
++
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
++ .lookup = squashfs_lookup
++};
++
++
++static struct buffer_head *get_block_length(struct super_block *s,
++ int *cur_index, int *offset, int *c_byte)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned short temp;
++ struct buffer_head *bh;
++
++ if (!(bh = sb_bread(s, *cur_index)))
++ goto out;
++
++ if (msblk->devblksize - *offset == 1) {
++ if (msblk->swap)
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ else
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ if (msblk->swap)
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ bh->b_data);
++ else
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ bh->b_data);
++ *c_byte = temp;
++ *offset = 1;
++ } else {
++ if (msblk->swap) {
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ } else {
++ ((unsigned char *) &temp)[0] = *((unsigned char *)
++ (bh->b_data + *offset));
++ ((unsigned char *) &temp)[1] = *((unsigned char *)
++ (bh->b_data + *offset + 1));
++ }
++ *c_byte = temp;
++ *offset += 2;
++ }
++
++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++ if (*offset == msblk->devblksize) {
++ brelse(bh);
++ if (!(bh = sb_bread(s, ++(*cur_index))))
++ goto out;
++ *offset = 0;
++ }
++ if (*((unsigned char *) (bh->b_data + *offset)) !=
++ SQUASHFS_MARKER_BYTE) {
++ ERROR("Metadata block marker corrupt @ %x\n",
++ *cur_index);
++ brelse(bh);
++ goto out;
++ }
++ (*offset)++;
++ }
++ return bh;
++
++out:
++ return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index, int srclength)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++ msblk->devblksize_log2) + 2];
++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++ unsigned int cur_index = index >> msblk->devblksize_log2;
++ int bytes, avail_bytes, b = 0, k = 0;
++ unsigned int compressed;
++ unsigned int c_byte = length;
++
++ if (c_byte) {
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte, srclength);
++
++ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
++
++ if (!(bh[0] = sb_getblk(s, cur_index)))
++ goto block_release;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b, bh);
++ } else {
++ if (index < 0 || (index + 2) > sblk->bytes_used)
++ goto read_failure;
++
++ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++ &c_byte)))
++ goto read_failure;
++
++ bytes = msblk->devblksize - offset;
++ compressed = SQUASHFS_COMPRESSED(c_byte);
++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++ ? "" : "un", (unsigned int) c_byte);
++
++ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
++ goto read_failure;
++
++ for (b = 1; bytes < c_byte; b++) {
++ if (!(bh[b] = sb_getblk(s, ++cur_index)))
++ goto block_release;
++ bytes += msblk->devblksize;
++ }
++ ll_rw_block(READ, b - 1, bh + 1);
++ }
++
++ if (compressed) {
++ int zlib_err = 0;
++
++ /*
++ * uncompress block
++ */
++
++ mutex_lock(&msblk->read_data_mutex);
++
++ msblk->stream.next_out = buffer;
++ msblk->stream.avail_out = srclength;
++
++ for (bytes = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto release_mutex;
++
++ msblk->stream.next_in = bh[k]->b_data + offset;
++ msblk->stream.avail_in = avail_bytes;
++
++ if (k == 0) {
++ zlib_err = zlib_inflateInit(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateInit returned unexpected result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++
++ if (avail_bytes == 0) {
++ offset = 0;
++ brelse(bh[k]);
++ continue;
++ }
++ }
++
++ zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
++ if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
++ ERROR("zlib_inflate returned unexpected result 0x%x, srclength %d, avail_in %d, avail_out %d\n",
++ zlib_err, srclength, msblk->stream.avail_in, msblk->stream.avail_out);
++ goto release_mutex;
++ }
++
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++
++ if (zlib_err != Z_STREAM_END)
++ goto release_mutex;
++
++ zlib_err = zlib_inflateEnd(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateEnd returned unexpected result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++ bytes = msblk->stream.total_out;
++ mutex_unlock(&msblk->read_data_mutex);
++ } else {
++ int i;
++
++ for(i = 0; i < b; i++) {
++ wait_on_buffer(bh[i]);
++ if(!buffer_uptodate(bh[i]))
++ goto block_release;
++ }
++
++ for (bytes = 0; k < b; k++) {
++ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++ msblk->devblksize - offset :
++ c_byte - bytes;
++ memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++ bytes += avail_bytes;
++ offset = 0;
++ brelse(bh[k]);
++ }
++ }
++
++ if (next_index)
++ *next_index = index + c_byte + (length ? 0 :
++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++ ? 3 : 2));
++ return bytes;
++
++release_mutex:
++ mutex_unlock(&msblk->read_data_mutex);
++
++block_release:
++ for (; k < b; k++)
++ brelse(bh[k]);
++
++read_failure:
++ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++ return 0;
++}
++
++
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ int n, i, bytes, return_length = length;
++ long long next_index;
++
++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++ while ( 1 ) {
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (msblk->block_cache[i].block == block)
++ break;
++
++ mutex_lock(&msblk->block_cache_mutex);
++
++ if (i == SQUASHFS_CACHED_BLKS) {
++ /* read inode header block */
++ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++ n ; n --, i = (i + 1) %
++ SQUASHFS_CACHED_BLKS)
++ if (msblk->block_cache[i].block !=
++ SQUASHFS_USED_BLK)
++ break;
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->waitq, &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ mutex_unlock(&msblk->block_cache_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->waitq, &wait);
++ continue;
++ }
++ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++ if (msblk->block_cache[i].block ==
++ SQUASHFS_INVALID_BLK) {
++ if (!(msblk->block_cache[i].data =
++ kmalloc(SQUASHFS_METADATA_SIZE,
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate cache"
++ "block\n");
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ }
++ }
++
++ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++ mutex_unlock(&msblk->block_cache_mutex);
++
++ msblk->block_cache[i].length = squashfs_read_data(s,
++ msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
++ if (msblk->block_cache[i].length == 0) {
++ ERROR("Unable to read cache block [%llx:%x]\n",
++ block, offset);
++ mutex_lock(&msblk->block_cache_mutex);
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++ kfree(msblk->block_cache[i].data);
++ wake_up(&msblk->waitq);
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ }
++
++ mutex_lock(&msblk->block_cache_mutex);
++ wake_up(&msblk->waitq);
++ msblk->block_cache[i].block = block;
++ msblk->block_cache[i].next_index = next_index;
++ TRACE("Read cache block [%llx:%x]\n", block, offset);
++ }
++
++ if (msblk->block_cache[i].block != block) {
++ mutex_unlock(&msblk->block_cache_mutex);
++ continue;
++ }
++
++ bytes = msblk->block_cache[i].length - offset;
++
++ if (bytes < 1) {
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto out;
++ } else if (bytes >= length) {
++ if (buffer)
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, length);
++ if (msblk->block_cache[i].length - offset == length) {
++ *next_block = msblk->block_cache[i].next_index;
++ *next_offset = 0;
++ } else {
++ *next_block = block;
++ *next_offset = offset + length;
++ }
++ mutex_unlock(&msblk->block_cache_mutex);
++ goto finish;
++ } else {
++ if (buffer) {
++ memcpy(buffer, msblk->block_cache[i].data +
++ offset, bytes);
++ buffer += bytes;
++ }
++ block = msblk->block_cache[i].next_index;
++ mutex_unlock(&msblk->block_cache_mutex);
++ length -= bytes;
++ offset = 0;
++ }
++ }
++
++finish:
++ return return_length;
++out:
++ return 0;
++}
++
++
++static int get_fragment_location(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++ struct squashfs_fragment_entry fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment)
++{
++ mutex_lock(&msblk->fragment_mutex);
++ fragment->locked --;
++ wake_up(&msblk->fragment_wait_queue);
++ mutex_unlock(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length)
++{
++ int i, n;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ while ( 1 ) {
++ mutex_lock(&msblk->fragment_mutex);
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++ msblk->fragment[i].block != start_block; i++);
++
++ if (i == SQUASHFS_CACHED_FRAGMENTS) {
++ for (i = msblk->next_fragment, n =
++ SQUASHFS_CACHED_FRAGMENTS; n &&
++ msblk->fragment[i].locked; n--, i = (i + 1) %
++ SQUASHFS_CACHED_FRAGMENTS);
++
++ if (n == 0) {
++ wait_queue_t wait;
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ mutex_unlock(&msblk->fragment_mutex);
++ schedule();
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&msblk->fragment_wait_queue,
++ &wait);
++ continue;
++ }
++ msblk->next_fragment = (msblk->next_fragment + 1) %
++ SQUASHFS_CACHED_FRAGMENTS;
++
++ if (msblk->fragment[i].data == NULL)
++ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++ (SQUASHFS_FILE_MAX_SIZE))) {
++ ERROR("Failed to allocate fragment "
++ "cache block\n");
++ mutex_unlock(&msblk->fragment_mutex);
++ goto out;
++ }
++
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].locked = 1;
++ mutex_unlock(&msblk->fragment_mutex);
++
++ if (!(msblk->fragment[i].length = squashfs_read_data(s,
++ msblk->fragment[i].data,
++ start_block, length, NULL, sblk->block_size))) {
++ ERROR("Unable to read fragment cache block "
++ "[%llx]\n", start_block);
++ msblk->fragment[i].locked = 0;
++ smp_mb();
++ goto out;
++ }
++
++ mutex_lock(&msblk->fragment_mutex);
++ msblk->fragment[i].block = start_block;
++ TRACE("New fragment %d, start block %lld, locked %d\n",
++ i, msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ mutex_unlock(&msblk->fragment_mutex);
++ break;
++ }
++
++ msblk->fragment[i].locked++;
++ mutex_unlock(&msblk->fragment_mutex);
++ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++ msblk->fragment[i].block,
++ msblk->fragment[i].locked);
++ break;
++ }
++
++ return &msblk->fragment[i];
++
++out:
++ return NULL;
++}
++
++
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
++ struct squashfs_base_inode_header *inodeb)
++{
++ i->i_ino = inodeb->inode_number;
++ i->i_mtime.tv_sec = inodeb->mtime;
++ i->i_atime.tv_sec = inodeb->mtime;
++ i->i_ctime.tv_sec = inodeb->mtime;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++}
++
++
++static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
++ int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
++ squashfs_inode_t inode;
++
++ TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
++
++ if (msblk->swap) {
++ squashfs_inode_t sinode;
++
++ if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
++ sizeof(sinode), &start, &offset))
++ goto out;
++ SQUASHFS_SWAP_INODE_T((&inode), &sinode);
++ } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
++ sizeof(inode), &start, &offset))
++ goto out;
++
++ TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
++
++ return inode;
++
++out:
++ return SQUASHFS_INVALID_BLK;
++}
++
++
++static void vfs_read_inode(struct inode *i)
++{
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
++
++ TRACE("Entered vfs_read_inode\n");
++
++ if(inode != SQUASHFS_INVALID_BLK)
++ (msblk->read_inode)(i, inode);
++}
++
++
++static struct dentry *squashfs_get_parent(struct dentry *child)
++{
++ struct inode *i = child->d_inode;
++ struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
++ struct dentry *rv;
++
++ TRACE("Entered squashfs_get_parent\n");
++
++ if(parent == NULL) {
++ rv = ERR_PTR(-EACCES);
++ goto out;
++ }
++
++ rv = d_alloc_anon(parent);
++ if(rv == NULL)
++ rv = ERR_PTR(-ENOMEM);
++
++out:
++ return rv;
++}
++
++
++SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct inode *i = iget_locked(s, inode_number);
++
++ TRACE("Entered squashfs_iget\n");
++
++ if(i && (i->i_state & I_NEW)) {
++ (msblk->read_inode)(i, inode);
++ unlock_new_inode(i);
++ }
++
++ return i;
++}
++
++
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
++{
++ struct super_block *s = i->i_sb;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header id, sid;
++ struct squashfs_base_inode_header *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_read_inode\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ squashfs_new_inode(msblk, i, inodeb);
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_reg_inode_header *inodep = &id.reg;
++ struct squashfs_reg_inode_header *sinodep = &sid.reg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_nlink = 1;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_LREG_TYPE: {
++ unsigned int frag_size;
++ long long frag_blk;
++ struct squashfs_lreg_inode_header *inodep = &id.lreg;
++ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %llx, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header *inodep = &id.dir;
++ struct squashfs_dir_inode_header *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops;
++ i->i_fop = &squashfs_dir_ops;
++ i->i_mode |= S_IFDIR;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header *inodep = &id.dev;
++ struct squashfs_dev_inode_header *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++ struct squashfs_ipc_inode_header *inodep = &id.ipc;
++ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_nlink = inodep->nlink;
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ return 1;
++
++failed_read:
++ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
++
++failed_read1:
++ make_bad_inode(i);
++ return 0;
++}
++
++
++static int read_inode_lookup_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
++
++ TRACE("In read_inode_lookup_table, length %d\n", length);
++
++ /* Allocate inode lookup table */
++ if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
++ ERROR("Failed to allocate inode lookup table\n");
++ return 0;
++ }
++
++ if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
++ sblk->lookup_table_start, length |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
++ ERROR("unable to read inode lookup table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long block;
++
++ for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
++ SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
++ &msblk->inode_lookup_table[i], 1);
++ msblk->inode_lookup_table[i] = block;
++ }
++ }
++
++ return 1;
++}
++
++
++static int read_fragment_index_table(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
++
++ if(length == 0)
++ return 1;
++
++ /* Allocate fragment index table */
++ if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment index table\n");
++ return 0;
++ }
++
++ if (!squashfs_read_data(s, (char *) msblk->fragment_index,
++ sblk->fragment_table_start, length |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ long long fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++ &msblk->fragment_index[i], 1);
++ msblk->fragment_index[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->read_inode = squashfs_read_inode;
++ msblk->read_blocklist = read_blocklist;
++ msblk->read_fragment_index_table = read_fragment_index_table;
++
++ if (sblk->s_major == 1) {
++ if (!squashfs_1_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 1.0 support enabled\n");
++ return 0;
++ }
++ } else if (sblk->s_major == 2) {
++ if (!squashfs_2_0_supported(msblk)) {
++ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++ "are unsupported\n");
++ SERROR("Please recompile with "
++ "Squashfs 2.0 support enabled\n");
++ return 0;
++ }
++ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++ SQUASHFS_MINOR) {
++ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++ "filesystem\n", sblk->s_major, sblk->s_minor);
++ SERROR("Please update your kernel\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)
++{
++ struct squashfs_sb_info *msblk;
++ struct squashfs_super_block *sblk;
++ int i;
++ char b[BDEVNAME_SIZE];
++ struct inode *root;
++
++ TRACE("Entered squashfs_read_superblock\n");
++
++ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
++ GFP_KERNEL))) {
++ ERROR("Failed to allocate superblock\n");
++ goto failure;
++ }
++ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
++ msblk = s->s_fs_info;
++ if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++ ERROR("Failed to allocate zlib workspace\n");
++ goto failure;
++ }
++ sblk = &msblk->sblk;
++
++ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
++ msblk->devblksize_log2 = ffz(~msblk->devblksize);
++
++ mutex_init(&msblk->read_data_mutex);
++ mutex_init(&msblk->read_page_mutex);
++ mutex_init(&msblk->block_cache_mutex);
++ mutex_init(&msblk->fragment_mutex);
++ mutex_init(&msblk->meta_index_mutex);
++
++ init_waitqueue_head(&msblk->waitq);
++ init_waitqueue_head(&msblk->fragment_wait_queue);
++
++ sblk->bytes_used = sizeof(struct squashfs_super_block);
++ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++ sizeof(struct squashfs_super_block) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
++ SERROR("unable to read superblock\n");
++ goto failed_mount;
++ }
++
++ /* Check it is a SQUASHFS superblock */
++ msblk->swap = 0;
++ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++ struct squashfs_super_block ssblk;
++
++ WARNING("Mounting a different endian SQUASHFS "
++ "filesystem on %s\n", bdevname(s->s_bdev, b));
++
++ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++ msblk->swap = 1;
++ } else {
++ SERROR("Can't find a SQUASHFS superblock on %s\n",
++ bdevname(s->s_bdev, b));
++ goto failed_mount;
++ }
++ }
++
++ /* Check the MAJOR & MINOR versions */
++ if(!supported_squashfs_filesystem(msblk, silent))
++ goto failed_mount;
++
++ /* Check the filesystem does not extend beyond the end of the
++ block device */
++ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
++ goto failed_mount;
++
++ /* Check the root inode for sanity */
++ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
++ goto failed_mount;
++
++ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
++ TRACE("Inodes are %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_INODES
++ (sblk->flags) ? "un" : "");
++ TRACE("Data is %scompressed\n",
++ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++ ? "un" : "");
++ TRACE("Check data is %s present in the filesystem\n",
++ SQUASHFS_CHECK_DATA(sblk->flags) ?
++ "" : "not");
++ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++ TRACE("Block size %d\n", sblk->block_size);
++ TRACE("Number of inodes %d\n", sblk->inodes);
++ if (sblk->s_major > 1)
++ TRACE("Number of fragments %d\n", sblk->fragments);
++ TRACE("Number of uids %d\n", sblk->no_uids);
++ TRACE("Number of gids %d\n", sblk->no_guids);
++ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++ if (sblk->s_major > 1)
++ TRACE("sblk->fragment_table_start %llx\n",
++ sblk->fragment_table_start);
++ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++ s->s_flags |= MS_RDONLY;
++ s->s_op = &squashfs_super_ops;
++
++ /* Init inode_table block pointer array */
++ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++ ERROR("Failed to allocate block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++ msblk->next_cache = 0;
++
++ /* Allocate read_page block */
++ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++ ERROR("Failed to allocate read_page block\n");
++ goto failed_mount;
++ }
++
++ /* Allocate uid and gid tables */
++ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ goto failed_mount;
++ }
++ msblk->guid = msblk->uid + sblk->no_uids;
++
++ if (msblk->swap) {
++ unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++ sblk->no_guids), (sizeof(unsigned int) * 8));
++ } else
++ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++ ((sblk->no_uids + sblk->no_guids) *
++ sizeof(unsigned int)) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
++ ERROR("unable to read uid/gid table\n");
++ goto failed_mount;
++ }
++
++
++ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++ goto allocate_root;
++
++ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++ ERROR("Failed to allocate fragment block cache\n");
++ goto failed_mount;
++ }
++
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++ msblk->fragment[i].locked = 0;
++ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++ msblk->fragment[i].data = NULL;
++ }
++
++ msblk->next_fragment = 0;
++
++ /* Allocate and read fragment index table */
++ if (msblk->read_fragment_index_table(s) == 0)
++ goto failed_mount;
++
++ if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
++ goto allocate_root;
++
++ /* Allocate and read inode lookup table */
++ if (read_inode_lookup_table(s) == 0)
++ goto failed_mount;
++
++ s->s_op = &squashfs_export_super_ops;
++ s->s_export_op = &squashfs_export_ops;
++
++allocate_root:
++ root = new_inode(s);
++ if ((msblk->read_inode)(root, sblk->root_inode) == 0)
++ goto failed_mount;
++ insert_inode_hash(root);
++
++ if ((s->s_root = d_alloc_root(root)) == NULL) {
++ ERROR("Root inode create failed\n");
++ iput(root);
++ goto failed_mount;
++ }
++
++ TRACE("Leaving squashfs_read_super\n");
++ return 0;
++
++failed_mount:
++ kfree(msblk->inode_lookup_table);
++ kfree(msblk->fragment_index);
++ kfree(msblk->fragment);
++ kfree(msblk->uid);
++ kfree(msblk->read_page);
++ kfree(msblk->block_cache);
++ kfree(msblk->fragment_index_2);
++ vfree(msblk->stream.workspace);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ return -EINVAL;
++
++failure:
++ return -ENOMEM;
++}
++
++
++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ TRACE("Entered squashfs_statfs\n");
++
++ buf->f_type = SQUASHFS_MAGIC;
++ buf->f_bsize = sblk->block_size;
++ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++ buf->f_bfree = buf->f_bavail = 0;
++ buf->f_files = sblk->inodes;
++ buf->f_ffree = 0;
++ buf->f_namelen = SQUASHFS_NAME_LEN;
++
++ return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++ long long block = SQUASHFS_I(inode)->start_block;
++ int offset = SQUASHFS_I(inode)->offset;
++ void *pageaddr = kmap(page);
++
++ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++ "%llx, offset %x\n", page->index,
++ SQUASHFS_I(inode)->start_block,
++ SQUASHFS_I(inode)->offset);
++
++ for (length = 0; length < index; length += bytes) {
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++ block, offset, PAGE_CACHE_SIZE, &block,
++ &offset))) {
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++ offset);
++ goto skip_read;
++ }
++ }
++
++ if (length != index) {
++ ERROR("(squashfs_symlink_readpage) length != index\n");
++ bytes = 0;
++ goto skip_read;
++ }
++
++ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++ i_size_read(inode) - length;
++
++ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++ offset, bytes, &block, &offset)))
++ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap(page);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++ struct meta_index *meta = NULL;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ int i;
++
++ mutex_lock(&msblk->meta_index_mutex);
++
++ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++ if(msblk->meta_index == NULL)
++ goto not_allocated;
++
++ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++ if (msblk->meta_index[i].inode_number == inode->i_ino &&
++ msblk->meta_index[i].offset >= offset &&
++ msblk->meta_index[i].offset <= index &&
++ msblk->meta_index[i].locked == 0) {
++ TRACE("locate_meta_index: entry %d, offset %d\n", i,
++ msblk->meta_index[i].offset);
++ meta = &msblk->meta_index[i];
++ offset = meta->offset;
++ }
++
++ if (meta)
++ meta->locked = 1;
++
++not_allocated:
++ mutex_unlock(&msblk->meta_index_mutex);
++
++ return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct meta_index *meta = NULL;
++ int i;
++
++ mutex_lock(&msblk->meta_index_mutex);
++
++ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++ if(msblk->meta_index == NULL) {
++ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++ ERROR("Failed to allocate meta_index\n");
++ goto failed;
++ }
++ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++ msblk->meta_index[i].inode_number = 0;
++ msblk->meta_index[i].locked = 0;
++ }
++ msblk->next_meta_index = 0;
++ }
++
++ for(i = SQUASHFS_META_NUMBER; i &&
++ msblk->meta_index[msblk->next_meta_index].locked; i --)
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ if(i == 0) {
++ TRACE("empty_meta_index: failed!\n");
++ goto failed;
++ }
++
++ TRACE("empty_meta_index: returned meta entry %d, %p\n",
++ msblk->next_meta_index,
++ &msblk->meta_index[msblk->next_meta_index]);
++
++ meta = &msblk->meta_index[msblk->next_meta_index];
++ msblk->next_meta_index = (msblk->next_meta_index + 1) %
++ SQUASHFS_META_NUMBER;
++
++ meta->inode_number = inode->i_ino;
++ meta->offset = offset;
++ meta->skip = skip;
++ meta->entries = 0;
++ meta->locked = 1;
++
++failed:
++ mutex_unlock(&msblk->meta_index_mutex);
++ return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++ meta->locked = 0;
++ smp_mb();
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++ long long *start_block, int *offset)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ unsigned int *block_listp;
++ int block = 0;
++
++ if (msblk->swap) {
++ char sblock_list[blocks << 2];
++
++ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++ ((unsigned int *)sblock_list), blocks);
++ } else
++ if (!squashfs_get_cached_block(s, block_list, *start_block,
++ *offset, blocks << 2, start_block, offset)) {
++ ERROR("Unable to read block list [%llx:%x]\n",
++ *start_block, *offset);
++ goto failure;
++ }
++
++ for (block_listp = (unsigned int *) block_list; blocks;
++ block_listp++, blocks --)
++ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++ return block;
++
++failure:
++ return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++ return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++ long long *index_block, int *index_offset,
++ long long *data_block, char *block_list)
++{
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++ int offset = 0;
++ struct meta_index *meta;
++ struct meta_entry *meta_entry;
++ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++ int cur_offset = SQUASHFS_I(inode)->offset;
++ long long cur_data_block = SQUASHFS_I(inode)->start_block;
++ int i;
++
++ index /= SQUASHFS_META_INDEXES * skip;
++
++ while ( offset < index ) {
++ meta = locate_meta_index(inode, index, offset + 1);
++
++ if (meta == NULL) {
++ if ((meta = empty_meta_index(inode, offset + 1,
++ skip)) == NULL)
++ goto all_done;
++ } else {
++ if(meta->entries == 0)
++ goto failed;
++ offset = index < meta->offset + meta->entries ? index :
++ meta->offset + meta->entries - 1;
++ meta_entry = &meta->meta_entry[offset - meta->offset];
++ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++ cur_offset = meta_entry->offset;
++ cur_data_block = meta_entry->data_block;
++ TRACE("get_meta_index: offset %d, meta->offset %d, "
++ "meta->entries %d\n", offset, meta->offset,
++ meta->entries);
++ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++ " data_block 0x%llx\n", cur_index_block,
++ cur_offset, cur_data_block);
++ }
++
++ for (i = meta->offset + meta->entries; i <= index &&
++ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++ int blocks = skip * SQUASHFS_META_INDEXES;
++
++ while (blocks) {
++ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++ blocks;
++ int res = read_block_index(inode->i_sb, block,
++ block_list, &cur_index_block,
++ &cur_offset);
++
++ if (res == -1)
++ goto failed;
++
++ cur_data_block += res;
++ blocks -= block;
++ }
++
++ meta_entry = &meta->meta_entry[i - meta->offset];
++ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++ meta_entry->offset = cur_offset;
++ meta_entry->data_block = cur_data_block;
++ meta->entries ++;
++ offset ++;
++ }
++
++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++ meta->offset, meta->entries);
++
++ release_meta_index(inode, meta);
++ }
++
++all_done:
++ *index_block = cur_index_block;
++ *index_offset = cur_offset;
++ *data_block = cur_data_block;
++
++ return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++ release_meta_index(inode, meta);
++ return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++ int readahead_blks, char *block_list,
++ unsigned short **block_p, unsigned int *bsize)
++{
++ long long block_ptr;
++ int offset;
++ long long block;
++ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++ block_list);
++
++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++ block);
++
++ if(res == -1)
++ goto failure;
++
++ index -= res;
++
++ while ( index ) {
++ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++ int res = read_block_index(inode->i_sb, blocks, block_list,
++ &block_ptr, &offset);
++ if (res == -1)
++ goto failure;
++ block += res;
++ index -= blocks;
++ }
++
++ if (read_block_index(inode->i_sb, 1, block_list,
++ &block_ptr, &offset) == -1)
++ goto failure;
++ *bsize = *((unsigned int *) block_list);
++
++ return block;
++
++failure:
++ return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char *block_list;
++ long long block;
++ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++ void *pageaddr;
++ struct squashfs_fragment_cache *fragment = NULL;
++ char *data_ptr = msblk->read_page;
++
++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++ int start_index = page->index & ~mask;
++ int end_index = start_index | mask;
++
++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
++ ERROR("Failed to allocate block_list\n");
++ goto skip_read;
++ }
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT))
++ goto skip_read;
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ if ((block = (msblk->read_blocklist)(inode, index, 1,
++ block_list, NULL, &bsize)) == 0)
++ goto skip_read;
++
++ mutex_lock(&msblk->read_page_mutex);
++
++ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++ block, bsize, NULL, sblk->block_size))) {
++ ERROR("Unable to read page, block %llx, size %x\n", block,
++ bsize);
++ mutex_unlock(&msblk->read_page_mutex);
++ goto skip_read;
++ }
++ } else {
++ if ((fragment = get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)->u.s1.fragment_size))
++ == NULL) {
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ (int) SQUASHFS_I(inode)->
++ u.s1.fragment_size);
++ goto skip_read;
++ }
++ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++ (i_size_read(inode) & (sblk->block_size
++ - 1));
++ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++ data_ptr = fragment->data;
++ }
++
++ for (i = start_index; i <= end_index && byte_offset < bytes;
++ i++, byte_offset += PAGE_CACHE_SIZE) {
++ struct page *push_page;
++ int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++ PAGE_CACHE_SIZE : bytes - byte_offset;
++
++ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++ bytes, i, byte_offset, avail);
++
++ push_page = (i == page->index) ? page :
++ grab_cache_page_nowait(page->mapping, i);
++
++ if (!push_page)
++ continue;
++
++ if (PageUptodate(push_page))
++ goto skip_page;
++
++ pageaddr = kmap_atomic(push_page, KM_USER0);
++ memcpy(pageaddr, data_ptr + byte_offset, avail);
++ memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(push_page);
++ SetPageUptodate(push_page);
++skip_page:
++ unlock_page(push_page);
++ if(i != page->index)
++ page_cache_release(push_page);
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || index < (i_size_read(inode) >>
++ sblk->block_log))
++ mutex_unlock(&msblk->read_page_mutex);
++ else
++ release_cached_fragment(msblk, fragment);
++
++ kfree(block_list);
++ return 0;
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ kfree(block_list);
++ return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned char *block_list;
++ long long block;
++ unsigned int bsize, bytes = 0;
++ void *pageaddr;
++
++ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++ page->index,
++ SQUASHFS_I(inode)->start_block);
++
++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT)) {
++ block_list = NULL;
++ goto skip_read;
++ }
++
++ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
++ ERROR("Failed to allocate block_list\n");
++ goto skip_read;
++ }
++
++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++ || page->index < (i_size_read(inode) >>
++ sblk->block_log)) {
++ block = (msblk->read_blocklist)(inode, page->index, 1,
++ block_list, NULL, &bsize);
++ if(block == 0)
++ goto skip_read;
++
++ mutex_lock(&msblk->read_page_mutex);
++ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++ bsize, NULL, sblk->block_size);
++ if (bytes) {
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, msblk->read_page, bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ block, bsize);
++ mutex_unlock(&msblk->read_page_mutex);
++ } else {
++ struct squashfs_fragment_cache *fragment =
++ get_cached_fragment(inode->i_sb,
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block,
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ if (fragment) {
++ bytes = i_size_read(inode) & (sblk->block_size - 1);
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++ u.s1.fragment_offset, bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ release_cached_fragment(msblk, fragment);
++ } else
++ ERROR("Unable to read page, block %llx, size %x\n",
++ SQUASHFS_I(inode)->
++ u.s1.fragment_start_block, (int)
++ SQUASHFS_I(inode)-> u.s1.fragment_size);
++ }
++
++skip_read:
++ pageaddr = kmap_atomic(page, KM_USER0);
++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++ kunmap_atomic(pageaddr, KM_USER0);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++
++ kfree(block_list);
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ f_pos =- 3;
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length + 3;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index *index;
++ char *str;
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_index\n");
++ goto failure;
++ }
++
++ index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ kfree(str);
++failure:
++ return length + 3;
++}
++
++
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ struct squashfs_dir_entry *dire;
++
++ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto finish;
++ }
++
++ while(file->f_pos < 3) {
++ char *name;
++ int size, i_ino;
++
++ if(file->f_pos == 0) {
++ name = ".";
++ size = 1;
++ i_ino = i->i_ino;
++ } else {
++ name = "..";
++ size = 2;
++ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++ }
++ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++ (unsigned int) dirent, name, size, (int)
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]);
++
++ if (filldir(dirent, name, size,
++ file->f_pos, i_ino,
++ squashfs_filetype_table[1]) < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos += size;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos,
++ dirh.inode_number + dire->inode_number,
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ }
++ }
++
++finish:
++ kfree(dire);
++ return 0;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ kfree(dire);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header dirh;
++ struct squashfs_dir_entry *dire;
++
++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto exit_lookup;
++ }
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_lookup;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (name[0] < dire->name[0])
++ goto exit_lookup;
++
++ if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
++ squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %d\n", name,
++ dirh.start_block, dire->offset,
++ dirh.inode_number + dire->inode_number);
++
++ inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
++
++ goto exit_lookup;
++ }
++ }
++ }
++
++exit_lookup:
++ kfree(dire);
++ if (inode)
++ return d_splice_alias(inode, dentry);
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_lookup;
++}
++
++
++static int squashfs_remount(struct super_block *s, int *flags, char *data)
++{
++ *flags |= MS_RDONLY;
++ return 0;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++ int i;
++
++ if (s->s_fs_info) {
++ struct squashfs_sb_info *sbi = s->s_fs_info;
++ if (sbi->block_cache)
++ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++ if (sbi->block_cache[i].block !=
++ SQUASHFS_INVALID_BLK)
++ kfree(sbi->block_cache[i].data);
++ if (sbi->fragment)
++ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
++ SQUASHFS_FREE(sbi->fragment[i].data);
++ kfree(sbi->fragment);
++ kfree(sbi->block_cache);
++ kfree(sbi->read_page);
++ kfree(sbi->uid);
++ kfree(sbi->fragment_index);
++ kfree(sbi->fragment_index_2);
++ kfree(sbi->meta_index);
++ vfree(sbi->stream.workspace);
++ kfree(s->s_fs_info);
++ s->s_fs_info = NULL;
++ }
++}
++
++
++static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data,
++ struct vfsmount *mnt)
++{
++ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
++ mnt);
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++ int err = init_inodecache();
++ if (err)
++ goto out;
++
++ printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
++ "Phillip Lougher\n");
++
++ if ((err = register_filesystem(&squashfs_fs_type)))
++ destroy_inodecache();
++
++out:
++ return err;
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++ unregister_filesystem(&squashfs_fs_type);
++ destroy_inodecache();
++}
++
++
++static struct kmem_cache * squashfs_inode_cachep;
++
++
++static struct inode *squashfs_alloc_inode(struct super_block *sb)
++{
++ struct squashfs_inode_info *ei;
++ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
++ if (!ei)
++ return NULL;
++ return &ei->vfs_inode;
++}
++
++
++static void squashfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
++}
++
++
++static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
++{
++ struct squashfs_inode_info *ei = foo;
++
++ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
++ SLAB_CTOR_CONSTRUCTOR)
++ inode_init_once(&ei->vfs_inode);
++}
++
++
++static int __init init_inodecache(void)
++{
++ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
++ sizeof(struct squashfs_inode_info),
++ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++ init_once, NULL);
++ if (squashfs_inode_cachep == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++
++static void destroy_inodecache(void)
++{
++ kmem_cache_destroy(squashfs_inode_cachep);
++}
++
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
++MODULE_LICENSE("GPL");
+diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/squashfs.h linux-2.6.22.1/fs/squashfs/squashfs.h
+--- linux-2.6.22.1.oorig/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/squashfs/squashfs.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,87 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs.h
++ */
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++#endif
++
++#ifdef SQUASHFS_TRACE
++#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
++#else
++#define TRACE(s, args...) {}
++#endif
++
++#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
++
++#define SERROR(s, args...) do { \
++ if (!silent) \
++ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
++ } while(0)
++
++#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
++
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
++{
++ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
++}
++
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
++#define SQSH_EXTERN
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++ long long index, unsigned int length,
++ long long *next_index, int srclength);
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
++ long long block, unsigned int offset,
++ int length, long long *next_block,
++ unsigned int *next_offset);
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++ squashfs_fragment_cache *fragment);
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++ *s, long long start_block,
++ int length);
++extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
++extern const struct address_space_operations squashfs_symlink_aops;
++extern const struct address_space_operations squashfs_aops;
++extern const struct address_space_operations squashfs_aops_4K;
++extern struct inode_operations squashfs_dir_inode_ops;
++#else
++#define SQSH_EXTERN static
++#endif
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
++#else
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ return 0;
++}
++#endif
+diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/squashfs2_0.c linux-2.6.22.1/fs/squashfs/squashfs2_0.c
+--- linux-2.6.22.1.oorig/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/fs/squashfs/squashfs2_0.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,742 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs2_0.c
++ */
++
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/zlib.h>
++#include <linux/fs.h>
++#include <linux/squashfs_fs_sb.h>
++#include <linux/squashfs_fs_i.h>
++
++#include "squashfs.h"
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
++ struct nameidata *);
++
++static struct file_operations squashfs_dir_ops_2 = {
++ .read = generic_read_dir,
++ .readdir = squashfs_readdir_2
++};
++
++static struct inode_operations squashfs_dir_inode_ops_2 = {
++ .lookup = squashfs_lookup_2
++};
++
++static unsigned char squashfs_filetype_table[] = {
++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static int read_fragment_index_table_2(struct super_block *s)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments), GFP_KERNEL))) {
++ ERROR("Failed to allocate uid/gid table\n");
++ return 0;
++ }
++
++ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
++ !squashfs_read_data(s, (char *)
++ msblk->fragment_index_2,
++ sblk->fragment_table_start,
++ SQUASHFS_FRAGMENT_INDEX_BYTES_2
++ (sblk->fragments) |
++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
++ ERROR("unable to read fragment index table\n");
++ return 0;
++ }
++
++ if (msblk->swap) {
++ int i;
++ unsigned int fragment;
++
++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
++ i++) {
++ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
++ &msblk->fragment_index_2[i], 1);
++ msblk->fragment_index_2[i] = fragment;
++ }
++ }
++
++ return 1;
++}
++
++
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
++ long long *fragment_start_block,
++ unsigned int *fragment_size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ long long start_block =
++ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
++ struct squashfs_fragment_entry_2 fragment_entry;
++
++ if (msblk->swap) {
++ struct squashfs_fragment_entry_2 sfragment_entry;
++
++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
++ start_block, offset,
++ sizeof(sfragment_entry), &start_block,
++ &offset))
++ goto out;
++ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
++ } else
++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
++ start_block, offset,
++ sizeof(fragment_entry), &start_block,
++ &offset))
++ goto out;
++
++ *fragment_start_block = fragment_entry.start_block;
++ *fragment_size = fragment_entry.size;
++
++ return 1;
++
++out:
++ return 0;
++}
++
++
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
++ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ i->i_ino = ino;
++ i->i_mtime.tv_sec = sblk->mkfs_time;
++ i->i_atime.tv_sec = sblk->mkfs_time;
++ i->i_ctime.tv_sec = sblk->mkfs_time;
++ i->i_uid = msblk->uid[inodeb->uid];
++ i->i_mode = inodeb->mode;
++ i->i_nlink = 1;
++ i->i_size = 0;
++ if (inodeb->guid == SQUASHFS_GUIDS)
++ i->i_gid = i->i_uid;
++ else
++ i->i_gid = msblk->guid[inodeb->guid];
++}
++
++
++static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
++{
++ struct super_block *s = i->i_sb;
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ unsigned int block = SQUASHFS_INODE_BLK(inode) +
++ sblk->inode_table_start;
++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++ unsigned int ino = i->i_ino;
++ long long next_block;
++ unsigned int next_offset;
++ union squashfs_inode_header_2 id, sid;
++ struct squashfs_base_inode_header_2 *inodeb = &id.base,
++ *sinodeb = &sid.base;
++
++ TRACE("Entered squashfs_iget\n");
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
++ offset, sizeof(*sinodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
++ sizeof(*sinodeb));
++ } else
++ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
++ offset, sizeof(*inodeb), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ squashfs_new_inode(msblk, i, inodeb, ino);
++
++ switch(inodeb->inode_type) {
++ case SQUASHFS_FILE_TYPE: {
++ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
++ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
++ long long frag_blk;
++ unsigned int frag_size = 0;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ frag_blk = SQUASHFS_INVALID_BLK;
++ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
++ !get_fragment_location_2(s,
++ inodep->fragment, &frag_blk, &frag_size))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_fop = &generic_ro_fops;
++ i->i_mode |= S_IFREG;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++ if (sblk->block_size > 4096)
++ i->i_data.a_ops = &squashfs_aops;
++ else
++ i->i_data.a_ops = &squashfs_aops_4K;
++
++ TRACE("File inode %x:%x, start_block %x, "
++ "block_list_start %llx, offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, next_block,
++ next_offset);
++ break;
++ }
++ case SQUASHFS_DIR_TYPE: {
++ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
++ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Directory inode %x:%x, start_block %x, offset "
++ "%x\n", SQUASHFS_INODE_BLK(inode),
++ offset, inodep->start_block,
++ inodep->offset);
++ break;
++ }
++ case SQUASHFS_LDIR_TYPE: {
++ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
++ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->file_size;
++ i->i_op = &squashfs_dir_inode_ops_2;
++ i->i_fop = &squashfs_dir_ops_2;
++ i->i_mode |= S_IFDIR;
++ i->i_mtime.tv_sec = inodep->mtime;
++ i->i_atime.tv_sec = inodep->mtime;
++ i->i_ctime.tv_sec = inodep->mtime;
++ SQUASHFS_I(i)->start_block = inodep->start_block;
++ SQUASHFS_I(i)->offset = inodep->offset;
++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
++ SQUASHFS_I(i)->u.s2.directory_index_offset =
++ next_offset;
++ SQUASHFS_I(i)->u.s2.directory_index_count =
++ inodep->i_count;
++ SQUASHFS_I(i)->u.s2.parent_inode = 0;
++
++ TRACE("Long directory inode %x:%x, start_block %x, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->start_block, inodep->offset);
++ break;
++ }
++ case SQUASHFS_SYMLINK_TYPE: {
++ struct squashfs_symlink_inode_header_2 *inodep =
++ &id.symlink;
++ struct squashfs_symlink_inode_header_2 *sinodep =
++ &sid.symlink;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
++ sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_size = inodep->symlink_size;
++ i->i_op = &page_symlink_inode_operations;
++ i->i_data.a_ops = &squashfs_symlink_aops;
++ i->i_mode |= S_IFLNK;
++ SQUASHFS_I(i)->start_block = next_block;
++ SQUASHFS_I(i)->offset = next_offset;
++
++ TRACE("Symbolic link inode %x:%x, start_block %llx, "
++ "offset %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ next_block, next_offset);
++ break;
++ }
++ case SQUASHFS_BLKDEV_TYPE:
++ case SQUASHFS_CHRDEV_TYPE: {
++ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
++ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
++
++ if (msblk->swap) {
++ if (!squashfs_get_cached_block(s, (char *)
++ sinodep, block, offset,
++ sizeof(*sinodep), &next_block,
++ &next_offset))
++ goto failed_read;
++ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
++ } else
++ if (!squashfs_get_cached_block(s, (char *)
++ inodep, block, offset,
++ sizeof(*inodep), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ i->i_mode |= (inodeb->inode_type ==
++ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
++ S_IFBLK;
++ init_special_inode(i, i->i_mode,
++ old_decode_dev(inodep->rdev));
++
++ TRACE("Device inode %x:%x, rdev %x\n",
++ SQUASHFS_INODE_BLK(inode), offset,
++ inodep->rdev);
++ break;
++ }
++ case SQUASHFS_FIFO_TYPE:
++ case SQUASHFS_SOCKET_TYPE: {
++
++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
++ ? S_IFIFO : S_IFSOCK;
++ init_special_inode(i, i->i_mode, 0);
++ break;
++ }
++ default:
++ ERROR("Unknown inode type %d in squashfs_iget!\n",
++ inodeb->inode_type);
++ goto failed_read1;
++ }
++
++ return 1;
++
++failed_read:
++ ERROR("Unable to read inode [%x:%x]\n", block, offset);
++
++failed_read1:
++ return 0;
++}
++
++
++static int get_dir_index_using_offset(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ long long f_pos)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 index;
++
++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++ i_count, (unsigned int) f_pos);
++
++ if (f_pos == 0)
++ goto finish;
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) &index,
++ index_start, index_offset,
++ sizeof(index), &index_start,
++ &index_offset);
++
++ if (index.index > f_pos)
++ break;
++
++ squashfs_get_cached_block(s, NULL, index_start, index_offset,
++ index.size + 1, &index_start,
++ &index_offset);
++
++ length = index.index;
++ *next_block = index.start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++
++finish:
++ return length;
++}
++
++
++static int get_dir_index_using_name(struct super_block *s, long long
++ *next_block, unsigned int *next_offset,
++ long long index_start,
++ unsigned int index_offset, int i_count,
++ const char *name, int size)
++{
++ struct squashfs_sb_info *msblk = s->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ int i, length = 0;
++ struct squashfs_dir_index_2 *index;
++ char *str;
++
++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
++
++ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_index\n");
++ goto failure;
++ }
++
++ index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
++ strncpy(str, name, size);
++ str[size] = '\0';
++
++ for (i = 0; i < i_count; i++) {
++ if (msblk->swap) {
++ struct squashfs_dir_index_2 sindex;
++ squashfs_get_cached_block(s, (char *) &sindex,
++ index_start, index_offset,
++ sizeof(sindex), &index_start,
++ &index_offset);
++ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
++ } else
++ squashfs_get_cached_block(s, (char *) index,
++ index_start, index_offset,
++ sizeof(struct squashfs_dir_index_2),
++ &index_start, &index_offset);
++
++ squashfs_get_cached_block(s, index->name, index_start,
++ index_offset, index->size + 1,
++ &index_start, &index_offset);
++
++ index->name[index->size + 1] = '\0';
++
++ if (strcmp(index->name, str) > 0)
++ break;
++
++ length = index->index;
++ *next_block = index->start_block + sblk->directory_table_start;
++ }
++
++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
++ kfree(str);
++failure:
++ return length;
++}
++
++
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ struct squashfs_dir_entry_2 *dire;
++
++ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto finish;
++ }
++
++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count,
++ file->f_pos);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block, next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block, next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset,
++ dire->size + 1, &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (file->f_pos >= length)
++ continue;
++
++ dire->name[dire->size + 1] = '\0';
++
++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
++ (unsigned int) dirent, dire->name,
++ dire->size + 1, (int) file->f_pos,
++ dirh.start_block, dire->offset,
++ squashfs_filetype_table[dire->type]);
++
++ if (filldir(dirent, dire->name, dire->size + 1,
++ file->f_pos, SQUASHFS_MK_VFS_INODE(
++ dirh.start_block, dire->offset),
++ squashfs_filetype_table[dire->type])
++ < 0) {
++ TRACE("Filldir returned less than 0\n");
++ goto finish;
++ }
++ file->f_pos = length;
++ }
++ }
++
++finish:
++ kfree(dire);
++ return 0;
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ kfree(dire);
++ return 0;
++}
++
++
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ const unsigned char *name = dentry->d_name.name;
++ int len = dentry->d_name.len;
++ struct inode *inode = NULL;
++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
++ struct squashfs_super_block *sblk = &msblk->sblk;
++ long long next_block = SQUASHFS_I(i)->start_block +
++ sblk->directory_table_start;
++ int next_offset = SQUASHFS_I(i)->offset, length = 0,
++ dir_count;
++ struct squashfs_dir_header_2 dirh;
++ struct squashfs_dir_entry_2 *dire;
++ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
++
++ TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
++
++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
++ ERROR("Failed to allocate squashfs_dir_entry\n");
++ goto exit_loop;
++ }
++
++ if (len > SQUASHFS_NAME_LEN)
++ goto exit_loop;
++
++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_start,
++ SQUASHFS_I(i)->u.s2.directory_index_offset,
++ SQUASHFS_I(i)->u.s2.directory_index_count, name,
++ len);
++
++ while (length < i_size_read(i)) {
++ /* read directory header */
++ if (msblk->swap) {
++ struct squashfs_dir_header_2 sdirh;
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
++ next_block, next_offset, sizeof(sdirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdirh);
++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
++ next_block, next_offset, sizeof(dirh),
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += sizeof(dirh);
++ }
++
++ dir_count = dirh.count + 1;
++ while (dir_count--) {
++ if (msblk->swap) {
++ struct squashfs_dir_entry_2 sdire;
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ &sdire, next_block,next_offset,
++ sizeof(sdire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(sdire);
++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
++ } else {
++ if (!squashfs_get_cached_block(i->i_sb, (char *)
++ dire, next_block,next_offset,
++ sizeof(*dire), &next_block,
++ &next_offset))
++ goto failed_read;
++
++ length += sizeof(*dire);
++ }
++
++ if (!squashfs_get_cached_block(i->i_sb, dire->name,
++ next_block, next_offset, dire->size + 1,
++ &next_block, &next_offset))
++ goto failed_read;
++
++ length += dire->size + 1;
++
++ if (sorted && name[0] < dire->name[0])
++ goto exit_loop;
++
++ if ((len == dire->size + 1) && !strncmp(name,
++ dire->name, len)) {
++ squashfs_inode_t ino =
++ SQUASHFS_MKINODE(dirh.start_block,
++ dire->offset);
++ unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
++ dire->offset);
++
++ TRACE("calling squashfs_iget for directory "
++ "entry %s, inode %x:%x, %lld\n", name,
++ dirh.start_block, dire->offset, ino);
++
++ inode = squashfs_iget(i->i_sb, ino, inode_number);
++
++ goto exit_loop;
++ }
++ }
++ }
++
++exit_loop:
++ kfree(dire);
++ d_add(dentry, inode);
++ return ERR_PTR(0);
++
++failed_read:
++ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
++ next_offset);
++ goto exit_loop;
++}
++
++
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_super_block *sblk = &msblk->sblk;
++
++ msblk->read_inode = squashfs_read_inode_2;
++ msblk->read_fragment_index_table = read_fragment_index_table_2;
++
++ sblk->bytes_used = sblk->bytes_used_2;
++ sblk->uid_start = sblk->uid_start_2;
++ sblk->guid_start = sblk->guid_start_2;
++ sblk->inode_table_start = sblk->inode_table_start_2;
++ sblk->directory_table_start = sblk->directory_table_start_2;
++ sblk->fragment_table_start = sblk->fragment_table_start_2;
++
++ return 1;
++}
+diff -rduNp linux-2.6.22.1.oorig/include/linux/aufs_type.h linux-2.6.22.1/include/linux/aufs_type.h
+--- linux-2.6.22.1.oorig/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/include/linux/aufs_type.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
++ *
++ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/* $Id: aufs_type.h,v 1.55 2007/05/14 03:40:57 sfjro Exp $ */
++
++#include <linux/ioctl.h>
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#define AUFS_VERSION "20070514"
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++typedef char aufs_bindex_t;
++#define AUFS_BRANCH_MAX 127
++#else
++typedef short aufs_bindex_t;
++#ifdef CONFIG_AUFS_BRANCH_MAX_511
++#define AUFS_BRANCH_MAX 511
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++#define AUFS_BRANCH_MAX 1023
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++#define AUFS_BRANCH_MAX 32767
++#else
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif
++
++#define AUFS_NAME "aufs"
++#define AUFS_FSTYPE AUFS_NAME
++
++#define AUFS_ROOT_INO 2
++#define AUFS_FIRST_INO 11
++
++#define AUFS_WH_PFX ".wh."
++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
++#define AUFS_DIRWH_DEF 3
++#define AUFS_RDCACHE_DEF 10 /* seconds */
++#define AUFS_WKQ_NAME AUFS_NAME "d"
++#define AUFS_NWKQ_DEF 4
++
++#ifdef CONFIG_AUFS_COMPAT
++#define AUFS_DIROPQ_NAME "__dir_opaque"
++#else
++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#endif
++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++/* will be whiteouted doubly */
++#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME
++#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plink"
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {AuCtlErr, AuCtlErr_Last};
++enum {
++ AuCtl_REFRESH, //AuCtl_REFRESHV,
++ //AuCtl_FLUSH_PLINK,
++ //AuCtl_CPUP,
++ AuCtl_CPDOWN, AuCtl_MVDOWN
++};
++
++struct aufs_ctl_cp {
++ int bsrc, bdst;
++ int err;
++};
++
++#define Type 'A'
++#define AUFS_CTL_REFRESH _IO(Type, AuCtl_REFRESH)
++//#define AUFS_CTL_REFRESHV _IO(Type, AuCtl_REFRESHV)
++//#define AUFS_CTL_FLUSH_PLINK _IOR(Type, AuCtl_FLUSH_PLINK)
++//#define AUFS_CTL_CPUP _IOWR(Type, AuCtl_CPUP, struct aufs_ctl_cp)
++#define AUFS_CTL_CPDOWN _IOWR(Type, AuCtl_CPDOWN, struct aufs_ctl_cp)
++#define AUFS_CTL_MVDOWN _IOWR(Type, AuCtl_MVDOWN, struct aufs_ctl_cp)
++#undef Type
++
++#endif /* __AUFS_TYPE_H__ */
+diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs.h linux-2.6.22.1/include/linux/squashfs_fs.h
+--- linux-2.6.22.1.oorig/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/include/linux/squashfs_fs.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,934 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a) vmalloc(a)
++#define SQUASHFS_FREE(a) vfree(a)
++#else
++#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a) kfree(a)
++#endif
++#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
++#define SQUASHFS_MAJOR 3
++#define SQUASHFS_MINOR 0
++#define SQUASHFS_MAGIC 0x73717368
++#define SQUASHFS_MAGIC_SWAP 0x68737173
++#define SQUASHFS_START 0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE 8192
++#define SQUASHFS_METADATA_LOG 13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE 65536
++#define SQUASHFS_FILE_LOG 16
++
++#define SQUASHFS_FILE_MAX_SIZE 65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS 256
++#define SQUASHFS_GUIDS 255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN 256
++
++#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK ((long long) -1)
++#define SQUASHFS_USED_BLK ((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI 0
++#define SQUASHFS_NOD 1
++#define SQUASHFS_CHECK 2
++#define SQUASHFS_NOF 3
++#define SQUASHFS_NO_FRAG 4
++#define SQUASHFS_ALWAYS_FRAG 5
++#define SQUASHFS_DUPLICATE 6
++#define SQUASHFS_EXPORT 7
++
++#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_EXPORT)
++
++#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
++ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++ (duplicate_checking << 6) | (exportable << 7))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE 1
++#define SQUASHFS_FILE_TYPE 2
++#define SQUASHFS_SYMLINK_TYPE 3
++#define SQUASHFS_BLKDEV_TYPE 4
++#define SQUASHFS_CHRDEV_TYPE 5
++#define SQUASHFS_FIFO_TYPE 6
++#define SQUASHFS_SOCKET_TYPE 7
++#define SQUASHFS_LDIR_TYPE 8
++#define SQUASHFS_LREG_TYPE 9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES 5
++#define SQUASHFS_IPC_TYPE 0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT (1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops. Inodes consist of a compressed block number, and an
++ * uncompressed offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
++ << 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
++ ((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a) ((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
++ sizeof(long long))
++
++/* inode lookup table defines */
++#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
++
++#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
++ sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS 8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG 64
++
++#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
++ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE 0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES 31
++#define SQUASHFS_META_NUMBER 8
++#define SQUASHFS_SLOTS 4
++
++struct meta_entry {
++ long long data_block;
++ unsigned int index_block;
++ unsigned short offset;
++ unsigned short pad;
++};
++
++struct meta_index {
++ unsigned int inode_number;
++ unsigned int offset;
++ unsigned short entries;
++ unsigned short skip;
++ unsigned short locked;
++ unsigned short pad;
++ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long squashfs_block_t;
++typedef long long squashfs_inode_t;
++
++struct squashfs_super_block {
++ unsigned int s_magic;
++ unsigned int inodes;
++ unsigned int bytes_used_2;
++ unsigned int uid_start_2;
++ unsigned int guid_start_2;
++ unsigned int inode_table_start_2;
++ unsigned int directory_table_start_2;
++ unsigned int s_major:16;
++ unsigned int s_minor:16;
++ unsigned int block_size_1:16;
++ unsigned int block_log:16;
++ unsigned int flags:8;
++ unsigned int no_uids:8;
++ unsigned int no_guids:8;
++ unsigned int mkfs_time /* time of filesystem creation */;
++ squashfs_inode_t root_inode;
++ unsigned int block_size;
++ unsigned int fragments;
++ unsigned int fragment_table_start_2;
++ long long bytes_used;
++ long long uid_start;
++ long long guid_start;
++ long long inode_table_start;
++ long long directory_table_start;
++ long long fragment_table_start;
++ long long lookup_table_start;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++ unsigned int index;
++ unsigned int start_block;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER \
++ unsigned int inode_type:4; \
++ unsigned int mode:12; \
++ unsigned int uid:8; \
++ unsigned int guid:8; \
++ unsigned int mtime; \
++ unsigned int inode_number;
++
++struct squashfs_base_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ squashfs_block_t start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ long long file_size;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int parent_inode;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header {
++ SQUASHFS_BASE_INODE_HEADER;
++ unsigned int nlink;
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int start_block;
++ unsigned int i_count:16;
++ unsigned int parent_inode;
++ struct squashfs_dir_index index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header {
++ struct squashfs_base_inode_header base;
++ struct squashfs_dev_inode_header dev;
++ struct squashfs_symlink_inode_header symlink;
++ struct squashfs_reg_inode_header reg;
++ struct squashfs_lreg_inode_header lreg;
++ struct squashfs_dir_inode_header dir;
++ struct squashfs_ldir_inode_header ldir;
++ struct squashfs_ipc_inode_header ipc;
++};
++
++struct squashfs_dir_entry {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ int inode_number:16;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++ unsigned int count:8;
++ unsigned int start_block;
++ unsigned int inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++ long long start_block;
++ unsigned int size;
++ unsigned int pending;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa. These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++ int bits;\
++ int b_pos;\
++ unsigned long long val;\
++ unsigned char *s;\
++ unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ipc_inode_header))\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dev_inode_header)); \
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_symlink_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_reg_inode_header));\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_lreg_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_dir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++ sizeof(struct squashfs_ldir_inode_header));\
++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++ SQUASHFS_SWAP((s)->index, d, 0, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++ SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++ SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 2);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 16)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 4);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 32)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ 64)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++ int entry;\
++ int bit_position;\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, n * bits / 8);\
++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++ bits)\
++ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int type:4;
++ unsigned int offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:4; /* index into uid table */
++ unsigned int guid:4; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++ SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_ipc_inode_header_1));\
++ SQUASHFS_SWAP((s)->type, d, 24, 4);\
++ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dev_inode_header_1));\
++ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_1));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_reg_inode_header_1));\
++ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++ sizeof(struct squashfs_dir_inode_header_1));\
++ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++ unsigned int index:27;
++ unsigned int start_block:29;
++ unsigned char size;
++ unsigned char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short rdev;
++} __attribute__ ((packed));
++
++struct squashfs_symlink_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned short symlink_size;
++ char symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int mtime;
++ unsigned int start_block;
++ unsigned int fragment;
++ unsigned int offset;
++ unsigned int file_size:32;
++ unsigned short block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:19;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++ unsigned int inode_type:4;
++ unsigned int mode:12; /* protection */
++ unsigned int uid:8; /* index into uid table */
++ unsigned int guid:8; /* index into guid table */
++ unsigned int file_size:27;
++ unsigned int offset:13;
++ unsigned int mtime;
++ unsigned int start_block:24;
++ unsigned int i_count:16;
++ struct squashfs_dir_index_2 index[0];
++} __attribute__ ((packed));
++
++union squashfs_inode_header_2 {
++ struct squashfs_base_inode_header_2 base;
++ struct squashfs_dev_inode_header_2 dev;
++ struct squashfs_symlink_inode_header_2 symlink;
++ struct squashfs_reg_inode_header_2 reg;
++ struct squashfs_dir_inode_header_2 dir;
++ struct squashfs_ldir_inode_header_2 ldir;
++ struct squashfs_ipc_inode_header_2 ipc;
++};
++
++struct squashfs_dir_header_2 {
++ unsigned int count:8;
++ unsigned int start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++ unsigned int offset:13;
++ unsigned int type:3;
++ unsigned int size:8;
++ char name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++ unsigned int start_block;
++ unsigned int size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++ SQUASHFS_MEMSET(s, d, n);\
++ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dev_inode_header_2)); \
++ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_symlink_inode_header_2));\
++ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_reg_inode_header_2));\
++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_dir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++ sizeof(struct squashfs_ldir_inode_header_2));\
++ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++ SQUASHFS_SWAP((s)->index, d, 0, 27);\
++ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++ SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++ SQUASHFS_SWAP((s)->count, d, 0, 8);\
++ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++ SQUASHFS_SWAP((s)->type, d, 13, 3);\
++ SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++ SQUASHFS_SWAP_START\
++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++ SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++ SQUASHFS_METADATA_SIZE - 1) / \
++ SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++ sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++ /* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, b_pos)
++#else
++ /* convert from big endian to little endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++ tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++ b_pos = pos % 8;\
++ val = 0;\
++ s = (unsigned char *)p + (pos / 8);\
++ d = ((unsigned char *) &val) + 7;\
++ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++ *d-- = *s++;\
++ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
++
++#endif
++#endif
+diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs_i.h linux-2.6.22.1/include/linux/squashfs_fs_i.h
+--- linux-2.6.22.1.oorig/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/include/linux/squashfs_fs_i.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,45 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_i.h
++ */
++
++struct squashfs_inode_info {
++ long long start_block;
++ unsigned int offset;
++ union {
++ struct {
++ long long fragment_start_block;
++ unsigned int fragment_size;
++ unsigned int fragment_offset;
++ long long block_list_start;
++ } s1;
++ struct {
++ long long directory_index_start;
++ unsigned int directory_index_offset;
++ unsigned int directory_index_count;
++ unsigned int parent_inode;
++ } s2;
++ } u;
++ struct inode vfs_inode;
++};
++#endif
+diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs_sb.h linux-2.6.22.1/include/linux/squashfs_fs_sb.h
+--- linux-2.6.22.1.oorig/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/include/linux/squashfs_fs_sb.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
++ * Phillip Lougher <phillip@lougher.org.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * squashfs_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++ long long block;
++ int length;
++ long long next_index;
++ char *data;
++};
++
++struct squashfs_fragment_cache {
++ long long block;
++ int length;
++ unsigned int locked;
++ char *data;
++};
++
++struct squashfs_sb_info {
++ struct squashfs_super_block sblk;
++ int devblksize;
++ int devblksize_log2;
++ int swap;
++ struct squashfs_cache *block_cache;
++ struct squashfs_fragment_cache *fragment;
++ int next_cache;
++ int next_fragment;
++ int next_meta_index;
++ unsigned int *uid;
++ unsigned int *guid;
++ long long *fragment_index;
++ unsigned int *fragment_index_2;
++ char *read_page;
++ struct mutex read_data_mutex;
++ struct mutex read_page_mutex;
++ struct mutex block_cache_mutex;
++ struct mutex fragment_mutex;
++ struct mutex meta_index_mutex;
++ wait_queue_head_t waitq;
++ wait_queue_head_t fragment_wait_queue;
++ struct meta_index *meta_index;
++ z_stream stream;
++ long long *inode_lookup_table;
++ int (*read_inode)(struct inode *i, squashfs_inode_t \
++ inode);
++ long long (*read_blocklist)(struct inode *inode, int \
++ index, int readahead_blks, char *block_list, \
++ unsigned short **block_p, unsigned int *bsize);
++ int (*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+diff -rduNp linux-2.6.22.1.oorig/init/Kconfig linux-2.6.22.1/init/Kconfig
+--- linux-2.6.22.1.oorig/init/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/init/Kconfig 2007-07-24 14:17:46.000000000 +0200
+@@ -246,23 +246,21 @@ config AUDITSYSCALL
+ ensure that INOTIFY is configured.
+
+ config IKCONFIG
+- tristate "Kernel .config support"
++ tristate "Kernel .miniconfig support"
+ ---help---
+- This option enables the complete Linux kernel ".config" file
++ This option enables the mini Linux kernel ".miniconfig" file
+ contents to be saved in the kernel. It provides documentation
+ of which kernel options are used in a running kernel or in an
+- on-disk kernel. This information can be extracted from the kernel
+- image file with the script scripts/extract-ikconfig and used as
+- input to rebuild the current kernel or to build another kernel.
+- It can also be extracted from a running kernel by reading
+- /proc/config.gz if enabled (below).
++ on-disk kernel.
++ It can be extracted from a running kernel by reading
++ /proc/miniconfig.gz if enabled (below).
+
+ config IKCONFIG_PROC
+- bool "Enable access to .config through /proc/config.gz"
++ bool "Enable access to .miniconfig through /proc/miniconfig.gz"
+ depends on IKCONFIG && PROC_FS
+ ---help---
+ This option enables access to the kernel configuration file
+- through /proc/config.gz.
++ through /proc/miniconfig.gz.
+
+ config LOG_BUF_SHIFT
+ int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
+diff -rduNp linux-2.6.22.1.oorig/init/LzmaDecode.c linux-2.6.22.1/init/LzmaDecode.c
+--- linux-2.6.22.1.oorig/init/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/init/LzmaDecode.c 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,588 @@
++/*
++ LzmaDecode.c
++ LZMA Decoder (optimized for Speed version)
++
++ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this Code, expressly permits you to
++ statically or dynamically link your Code (or bind by name) to the
++ interfaces of this file without subjecting your linked Code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "LzmaDecode.h"
++
++#ifndef Byte
++#define Byte unsigned char
++#endif
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_READ_BYTE (*Buffer++)
++
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
++
++#ifdef _LZMA_IN_CB
++
++#define RC_TEST { if (Buffer == BufferLim) \
++ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
++
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
++
++#else
++
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
++
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
++
++#endif
++
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
++
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
++
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
++ { UpdateBit0(p); mi <<= 1; A0; } else \
++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
++
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
++
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
++ { int i = numLevels; res = 1; \
++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
++ res -= (1 << numLevels); }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
++{
++ unsigned char prop0;
++ if (size < LZMA_PROPERTIES_SIZE)
++ return LZMA_RESULT_DATA_ERROR;
++ prop0 = propsData[0];
++ if (prop0 >= (9 * 5 * 5))
++ return LZMA_RESULT_DATA_ERROR;
++ {
++ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
++ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
++ propsRes->lc = prop0;
++ /*
++ unsigned char remainder = (unsigned char)(prop0 / 9);
++ propsRes->lc = prop0 % 9;
++ propsRes->pb = remainder / 5;
++ propsRes->lp = remainder % 5;
++ */
++ }
++
++ #ifdef _LZMA_OUT_READ
++ {
++ int i;
++ propsRes->DictionarySize = 0;
++ for (i = 0; i < 4; i++)
++ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
++ if (propsRes->DictionarySize == 0)
++ propsRes->DictionarySize = 1;
++ }
++ #endif
++ return LZMA_RESULT_OK;
++}
++
++#define kLzmaStreamWasFinishedId (-1)
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *InCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
++{
++ CProb *p = vs->Probs;
++ SizeT nowPos = 0;
++ Byte previousByte = 0;
++ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
++ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
++ int lc = vs->Properties.lc;
++
++ #ifdef _LZMA_OUT_READ
++
++ UInt32 Range = vs->Range;
++ UInt32 Code = vs->Code;
++ #ifdef _LZMA_IN_CB
++ const Byte *Buffer = vs->Buffer;
++ const Byte *BufferLim = vs->BufferLim;
++ #else
++ const Byte *Buffer = inStream;
++ const Byte *BufferLim = inStream + inSize;
++ #endif
++ int state = vs->State;
++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
++ int len = vs->RemainLen;
++ UInt32 globalPos = vs->GlobalPos;
++ UInt32 distanceLimit = vs->DistanceLimit;
++
++ Byte *dictionary = vs->Dictionary;
++ UInt32 dictionarySize = vs->Properties.DictionarySize;
++ UInt32 dictionaryPos = vs->DictionaryPos;
++
++ Byte tempDictionary[4];
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++ if (len == kLzmaStreamWasFinishedId)
++ return LZMA_RESULT_OK;
++
++ if (dictionarySize == 0)
++ {
++ dictionary = tempDictionary;
++ dictionarySize = 1;
++ tempDictionary[0] = vs->TempDictionary[0];
++ }
++
++ if (len == kLzmaNeedInitId)
++ {
++ {
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ UInt32 i;
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ rep0 = rep1 = rep2 = rep3 = 1;
++ state = 0;
++ globalPos = 0;
++ distanceLimit = 0;
++ dictionaryPos = 0;
++ dictionary[dictionarySize - 1] = 0;
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++ }
++ len = 0;
++ }
++ while(len != 0 && nowPos < outSize)
++ {
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ len--;
++ }
++ if (dictionaryPos == 0)
++ previousByte = dictionary[dictionarySize - 1];
++ else
++ previousByte = dictionary[dictionaryPos - 1];
++
++ #else /* if !_LZMA_OUT_READ */
++
++ int state = 0;
++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++ int len = 0;
++ const Byte *Buffer;
++ const Byte *BufferLim;
++ UInt32 Range;
++ UInt32 Code;
++
++ #ifndef _LZMA_IN_CB
++ *inSizeProcessed = 0;
++ #endif
++ *outSizeProcessed = 0;
++
++ {
++ UInt32 i;
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++ for (i = 0; i < numProbs; i++)
++ p[i] = kBitModelTotal >> 1;
++ }
++
++ #ifdef _LZMA_IN_CB
++ RC_INIT;
++ #else
++ RC_INIT(inStream, inSize);
++ #endif
++
++ #endif /* _LZMA_OUT_READ */
++
++ while(nowPos < outSize)
++ {
++ CProb *prob;
++ UInt32 bound;
++ int posState = (int)(
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & posStateMask);
++
++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ int symbol = 1;
++ UpdateBit0(prob)
++ prob = p + Literal + (LZMA_LIT_SIZE *
++ (((
++ (nowPos
++ #ifdef _LZMA_OUT_READ
++ + globalPos
++ #endif
++ )
++ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++ if (state >= kNumLitStates)
++ {
++ int matchByte;
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ matchByte = dictionary[pos];
++ #else
++ matchByte = outStream[nowPos - rep0];
++ #endif
++ do
++ {
++ int bit;
++ CProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & 0x100);
++ probLit = prob + 0x100 + bit + symbol;
++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
++ }
++ while (symbol < 0x100);
++ }
++ while (symbol < 0x100)
++ {
++ CProb *probLit = prob + symbol;
++ RC_GET_BIT(probLit, symbol)
++ }
++ previousByte = (Byte)symbol;
++
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #endif
++ if (state < 4) state = 0;
++ else if (state < 10) state -= 3;
++ else state -= 6;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRep + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ state = state < kNumLitStates ? 0 : 3;
++ prob = p + LenCoder;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG0 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IfBit0(prob)
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos;
++ #endif
++ UpdateBit0(prob);
++
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit == 0)
++ #else
++ if (nowPos == 0)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ state = state < kNumLitStates ? 9 : 11;
++ #ifdef _LZMA_OUT_READ
++ pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ outStream[nowPos++] = previousByte;
++ #ifdef _LZMA_OUT_READ
++ if (distanceLimit < dictionarySize)
++ distanceLimit++;
++ #endif
++
++ continue;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ }
++ }
++ else
++ {
++ UInt32 distance;
++ UpdateBit1(prob);
++ prob = p + IsRepG1 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep1;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ prob = p + IsRepG2 + state;
++ IfBit0(prob)
++ {
++ UpdateBit0(prob);
++ distance = rep2;
++ }
++ else
++ {
++ UpdateBit1(prob);
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ state = state < kNumLitStates ? 8 : 11;
++ prob = p + RepLenCoder;
++ }
++ {
++ int numBits, offset;
++ CProb *probLen = prob + LenChoice;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ numBits = kLenNumLowBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenChoice2;
++ IfBit0(probLen)
++ {
++ UpdateBit0(probLen);
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ numBits = kLenNumMidBits;
++ }
++ else
++ {
++ UpdateBit1(probLen);
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ numBits = kLenNumHighBits;
++ }
++ }
++ RangeDecoderBitTreeDecode(probLen, numBits, len);
++ len += offset;
++ }
++
++ if (state < 4)
++ {
++ int posSlot;
++ state += kNumLitStates;
++ prob = p + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits);
++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++ rep0 = (2 | ((UInt32)posSlot & 1));
++ if (posSlot < kEndPosModelIndex)
++ {
++ rep0 <<= numDirectBits;
++ prob = p + SpecPos + rep0 - posSlot - 1;
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ RC_NORMALIZE
++ Range >>= 1;
++ rep0 <<= 1;
++ if (Code >= Range)
++ {
++ Code -= Range;
++ rep0 |= 1;
++ }
++ }
++ while (--numDirectBits != 0);
++ prob = p + Align;
++ rep0 <<= kNumAlignBits;
++ numDirectBits = kNumAlignBits;
++ }
++ {
++ int i = 1;
++ int mi = 1;
++ do
++ {
++ CProb *prob3 = prob + mi;
++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
++ i <<= 1;
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ else
++ rep0 = posSlot;
++ if (++rep0 == (UInt32)(0))
++ {
++ /* it's for stream version */
++ len = kLzmaStreamWasFinishedId;
++ break;
++ }
++ }
++
++ len += kMatchMinLen;
++ #ifdef _LZMA_OUT_READ
++ if (rep0 > distanceLimit)
++ #else
++ if (rep0 > nowPos)
++ #endif
++ return LZMA_RESULT_DATA_ERROR;
++
++ #ifdef _LZMA_OUT_READ
++ if (dictionarySize - distanceLimit > (UInt32)len)
++ distanceLimit += len;
++ else
++ distanceLimit = dictionarySize;
++ #endif
++
++ do
++ {
++ #ifdef _LZMA_OUT_READ
++ UInt32 pos = dictionaryPos - rep0;
++ if (pos >= dictionarySize)
++ pos += dictionarySize;
++ previousByte = dictionary[pos];
++ dictionary[dictionaryPos] = previousByte;
++ if (++dictionaryPos == dictionarySize)
++ dictionaryPos = 0;
++ #else
++ previousByte = outStream[nowPos - rep0];
++ #endif
++ len--;
++ outStream[nowPos++] = previousByte;
++ }
++ while(len != 0 && nowPos < outSize);
++ }
++ }
++ RC_NORMALIZE;
++
++ #ifdef _LZMA_OUT_READ
++ vs->Range = Range;
++ vs->Code = Code;
++ vs->DictionaryPos = dictionaryPos;
++ vs->GlobalPos = globalPos + (UInt32)nowPos;
++ vs->DistanceLimit = distanceLimit;
++ vs->Reps[0] = rep0;
++ vs->Reps[1] = rep1;
++ vs->Reps[2] = rep2;
++ vs->Reps[3] = rep3;
++ vs->State = state;
++ vs->RemainLen = len;
++ vs->TempDictionary[0] = tempDictionary[0];
++ #endif
++
++ #ifdef _LZMA_IN_CB
++ vs->Buffer = Buffer;
++ vs->BufferLim = BufferLim;
++ #else
++ *inSizeProcessed = (SizeT)(Buffer - inStream);
++ #endif
++ *outSizeProcessed = nowPos;
++ return LZMA_RESULT_OK;
++}
+diff -rduNp linux-2.6.22.1.oorig/init/LzmaDecode.h linux-2.6.22.1/init/LzmaDecode.h
+--- linux-2.6.22.1.oorig/init/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/init/LzmaDecode.h 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,131 @@
++/*
++ LzmaDecode.h
++ LZMA Decoder interface
++
++ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
++ http://www.7-zip.org/
++
++ LZMA SDK is licensed under two licenses:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ It means that you can select one of these two licenses and
++ follow rules of that license.
++
++ SPECIAL EXCEPTION:
++ Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to the
++ interfaces of this file without subjecting your linked code to the
++ terms of the CPL or GNU LGPL. Any modifications or additions
++ to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++/* #define _LZMA_IN_CB */
++/* Use callback for input data */
++
++/* #define _LZMA_OUT_READ */
++/* Use read function for output data */
++
++/* #define _LZMA_PROB32 */
++/* It can increase speed on some 32-bit CPUs,
++ but memory usage will be doubled in that case */
++
++/* #define _LZMA_LOC_OPT */
++/* Enable local speed optimizations inside code */
++
++/* #define _LZMA_SYSTEM_SIZE_T */
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
++
++#ifndef UInt32
++#ifdef _LZMA_UINT32_IS_ULONG
++#define UInt32 unsigned long
++#else
++#define UInt32 unsigned int
++#endif
++#endif
++
++#ifndef SizeT
++#ifdef _LZMA_SYSTEM_SIZE_T
++#include <stddef.h>
++#define SizeT size_t
++#else
++#define SizeT UInt32
++#endif
++#endif
++
++#ifdef _LZMA_PROB32
++#define CProb UInt32
++#else
++#define CProb unsigned short
++#endif
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++
++#ifdef _LZMA_IN_CB
++typedef struct _ILzmaInCallback
++{
++ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
++} ILzmaInCallback;
++#endif
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_PROPERTIES_SIZE 5
++
++typedef struct _CLzmaProperties
++{
++ int lc;
++ int lp;
++ int pb;
++ #ifdef _LZMA_OUT_READ
++ UInt32 DictionarySize;
++ #endif
++}CLzmaProperties;
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
++
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
++
++#define kLzmaNeedInitId (-2)
++
++typedef struct _CLzmaDecoderState
++{
++ CLzmaProperties Properties;
++ CProb *Probs;
++
++ #ifdef _LZMA_IN_CB
++ const unsigned char *Buffer;
++ const unsigned char *BufferLim;
++ #endif
++
++ #ifdef _LZMA_OUT_READ
++ unsigned char *Dictionary;
++ UInt32 Range;
++ UInt32 Code;
++ UInt32 DictionaryPos;
++ UInt32 GlobalPos;
++ UInt32 DistanceLimit;
++ UInt32 Reps[4];
++ int State;
++ int RemainLen;
++ unsigned char TempDictionary[4];
++ #endif
++} CLzmaDecoderState;
++
++#ifdef _LZMA_OUT_READ
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
++#endif
++
++int LzmaDecode(CLzmaDecoderState *vs,
++ #ifdef _LZMA_IN_CB
++ ILzmaInCallback *inCallback,
++ #else
++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++ #endif
++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
++
++#endif
+diff -rduNp linux-2.6.22.1.oorig/init/do_mounts_rd.c linux-2.6.22.1/init/do_mounts_rd.c
+--- linux-2.6.22.1.oorig/init/do_mounts_rd.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/init/do_mounts_rd.c 2007-07-24 14:17:46.000000000 +0200
+@@ -5,7 +5,9 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+ #include <linux/cramfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/initrd.h>
++#include <linux/vmalloc.h>
+ #include <linux/string.h>
+
+ #include "do_mounts.h"
+@@ -31,6 +33,9 @@ static int __init ramdisk_start_setup(ch
+ __setup("ramdisk_start=", ramdisk_start_setup);
+
+ static int __init crd_load(int in_fd, int out_fd);
++#ifdef CONFIG_LZMA_INITRD
++static int __init lzma_rd_load(int in_fd, int out_fd);
++#endif
+
+ /*
+ * This routine tries to find a RAM disk image to load, and returns the
+@@ -39,6 +44,7 @@ static int __init crd_load(int in_fd, in
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
++ * squashfs
+ * minix
+ * ext2
+ * romfs
+@@ -53,6 +59,7 @@ identify_ramdisk_image(int fd, int start
+ struct ext2_super_block *ext2sb;
+ struct romfs_super_block *romfsb;
+ struct cramfs_super *cramfsb;
++ struct squashfs_super_block *squashfsb;
+ int nblocks = -1;
+ unsigned char *buf;
+
+@@ -64,6 +71,7 @@ identify_ramdisk_image(int fd, int start
+ ext2sb = (struct ext2_super_block *) buf;
+ romfsb = (struct romfs_super_block *) buf;
+ cramfsb = (struct cramfs_super *) buf;
++ squashfsb = (struct squashfs_super_block *) buf;
+ memset(buf, 0xe5, size);
+
+ /*
+@@ -82,6 +90,17 @@ identify_ramdisk_image(int fd, int start
+ nblocks = 0;
+ goto done;
+ }
++ /*
++ * handle lzma compressed initrd, returns nblocks=1 as indication
++ */
++ if( buf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0 && buf[11] == 0
++ && buf[12] == 0 )
++ {
++ printk( KERN_NOTICE "RAMDISK: LZMA image found at block %d\n",
++ start_block);
++ nblocks = 1; // just a convenient return flag
++ goto done;
++ }
+
+ /* romfs is at block zero too */
+ if (romfsb->word0 == ROMSB_WORD0 &&
+@@ -101,6 +120,18 @@ identify_ramdisk_image(int fd, int start
+ goto done;
+ }
+
++ /* squashfs is at block zero too */
++ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++ printk(KERN_NOTICE
++ "RAMDISK: squashfs filesystem found at block %d\n",
++ start_block);
++ if (squashfsb->s_major < 3)
++ nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ else
++ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++ goto done;
++ }
++
+ /*
+ * Read block 1 to test for minix and ext2 superblock
+ */
+@@ -172,7 +203,22 @@ int __init rd_load_image(char *from)
+ #endif
+ goto done;
+ }
+-
++#ifdef CONFIG_LZMA_INITRD
++ /*
++ * handle lzma compressed image
++ */
++ if ( nblocks == 1 )
++ {
++ nblocks = 0;
++ if ( lzma_rd_load(in_fd, out_fd) == 0 )
++ {
++ printk("\nLZMA initrd loaded successfully\n");
++ goto successful_load;
++ }
++ printk(KERN_NOTICE "LZMA initrd is not in the correct format\n");
++ goto done;
++ }
++#endif
+ /*
+ * NOTE NOTE: nblocks is not actually blocks but
+ * the number of kibibytes of data to load into a ramdisk.
+@@ -393,6 +439,134 @@ static void __init error(char *x)
+ unzip_error = 1;
+ }
+
++#ifdef CONFIG_LZMA_INITRD
++#define _LZMA_IN_CB
++#define _LZMA_OUT_READ
++#include "LzmaDecode.h"
++#include "LzmaDecode.c"
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
++
++/*
++ * Do the lzma decompression
++ */
++static int __init lzma_rd_load(int in_fd, int out_fd)
++{
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned char* outputbuffer;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++ unsigned int kBlockSize = 0x10000;
++ unsigned int nowPos = 0;
++ unsigned int outsizeProcessed = 0;
++ int res;
++ ILzmaInCallback callback;
++
++ insize = 0; /* valid bytes in inbuf */
++ inptr = 0; /* index of next byte to be processed in inbuf */
++ exit_code = 0;
++ crd_infd = in_fd;
++ inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
++ if (inbuf == 0)
++ {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma input buffer\n");
++ return -1;
++ }
++
++ callback.Read = read_byte;
++
++ /* lzma args */
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ /* read dictionary size */
++ p = (char*)&state.Properties.DictionarySize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ /* get uncompressedSize */
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ /* skip big file */
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ printk( KERN_NOTICE "RAMDISK: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
++ state.Properties.lc, state.Properties.lp, state.Properties.pb, state.Properties.DictionarySize, uncompressedSize);
++ outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
++ if (outputbuffer == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma output buffer\n");
++ return -1;
++ }
++
++ state.Probs = (CProb*)kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
++ if ( state.Probs == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma workspace\n");
++ return -1;
++ }
++
++#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
++ state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
++#else
++ state.Dictionary = vmalloc( state.Properties.DictionarySize);
++#endif
++ if ( state.Dictionary == 0) {
++ printk(KERN_ERR "RAMDISK: Couldn't allocate lzma dictionary\n");
++ return -1;
++ }
++
++ printk( KERN_NOTICE "LZMA initrd by Ming-Ching Tiew <mctiew@yahoo.com> " );
++
++ LzmaDecoderInit( &state );
++
++ for( nowPos =0; nowPos < uncompressedSize ; )
++ {
++ UInt32 blockSize = uncompressedSize - nowPos;
++ if( blockSize > kBlockSize)
++ blockSize = kBlockSize;
++ res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
++ if( res != 0 ) {
++ printk( KERN_ERR "RAMDISK: Lzma decode failure\n");
++ return -1;
++ }
++ if( outsizeProcessed == 0 )
++ {
++ uncompressedSize = nowPos;
++ printk( KERN_NOTICE "RAMDISK nowPos=%d, uncompressedSize=%d\n",
++ nowPos, uncompressedSize );
++ break;
++ }
++ sys_write(out_fd, outputbuffer, outsizeProcessed );
++ nowPos += outsizeProcessed;
++ printk( ".");
++ }
++
++#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
++ kfree(state.Dictionary);
++#else
++ vfree(state.Dictionary);
++#endif
++ kfree(inbuf);
++ kfree(outputbuffer);
++ kfree(state.Probs);
++ return 0;
++}
++
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++#endif /*CONFIG_LZMA_INITRD*/
++
+ static int __init crd_load(int in_fd, int out_fd)
+ {
+ int result;
+diff -rduNp linux-2.6.22.1.oorig/init/initramfs.c linux-2.6.22.1/init/initramfs.c
+--- linux-2.6.22.1.oorig/init/initramfs.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/init/initramfs.c 2007-07-24 14:17:46.000000000 +0200
+@@ -6,6 +6,7 @@
+ #include <linux/delay.h>
+ #include <linux/string.h>
+ #include <linux/syscalls.h>
++#include <linux/vmalloc.h>
+
+ static __initdata char *message;
+ static void __init error(char *x)
+@@ -441,6 +442,118 @@ static void __init flush_window(void)
+ outcnt = 0;
+ }
+
++#ifdef CONFIG_LZMA_INITRAM_FS
++#define _LZMA_IN_CB
++#define _LZMA_OUT_READ
++#include "LzmaDecode.h"
++#ifndef CONFIG_LZMA_INITRD
++ #include "LzmaDecode.c"
++#endif
++static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
++{
++ static unsigned char val;
++ *bufferSize = 1;
++ val = get_byte();
++ *buffer = &val;
++ return LZMA_RESULT_OK;
++}
++
++static int __init lzma_unzip(void)
++{
++ unsigned int i;
++ CLzmaDecoderState state;
++ unsigned char* outputbuffer;
++ unsigned int uncompressedSize = 0;
++ unsigned char* p;
++ unsigned int kBlockSize = 0x10000;
++ unsigned int nowPos = 0;
++ unsigned int outsizeProcessed = 0;
++ int res;
++ ILzmaInCallback callback;
++
++ callback.Read = read_byte;
++
++ // lzma args
++ i = get_byte();
++ state.Properties.lc = i % 9, i = i / 9;
++ state.Properties.lp = i % 5, state.Properties.pb = i / 5;
++
++ // read dictionary size
++ p = (char*)&state.Properties.DictionarySize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // get uncompressedSize
++ p= (char*)&uncompressedSize;
++ for (i = 0; i < 4; i++)
++ *p++ = get_byte();
++
++ // skip big file
++ for (i = 0; i < 4; i++)
++ get_byte();
++
++ printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
++ state.Properties.lc,state.Properties.lp,state.Properties.pb,state.Properties.DictionarySize, uncompressedSize);
++ outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
++ if (outputbuffer == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
++ return -1;
++ }
++
++ state.Probs = (CProb*) kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
++ if ( state.Probs == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
++ return -1;
++ }
++
++#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
++ state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
++#else
++ state.Dictionary = vmalloc( state.Properties.DictionarySize);
++#endif
++ if ( state.Dictionary == 0) {
++ printk(KERN_ERR "initramfs: Couldn't allocate lzma dictionary\n");
++ return -1;
++ }
++
++ printk( KERN_NOTICE "LZMA initramfs by Ming-Ching Tiew <mctiew@yahoo.com> " );
++
++ LzmaDecoderInit( &state );
++
++ for( nowPos =0; nowPos < uncompressedSize ; )
++ {
++ UInt32 blockSize = uncompressedSize - nowPos;
++ if( blockSize > kBlockSize)
++ blockSize = kBlockSize;
++ res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
++ if( res != 0 ) {
++ panic( KERN_ERR "initramfs: Lzma decode failure\n");
++ return -1;
++ }
++ if( outsizeProcessed == 0 )
++ {
++ uncompressedSize = nowPos;
++ printk( KERN_NOTICE "initramfs: nowPos=%d, uncompressedSize=%d\n",
++ nowPos, uncompressedSize );
++ break;
++ }
++ flush_buffer(outputbuffer, outsizeProcessed);
++ nowPos += outsizeProcessed;
++ printk( ".");
++ }
++
++#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
++ kfree(state.Dictionary);
++#else
++ vfree(state.Dictionary);
++#endif
++ kfree(outputbuffer);
++ kfree(state.Probs);
++ return 0;
++}
++
++#endif /*CONFIG LZMA_INITRAM_FS*/
++
+ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ {
+ int written;
+@@ -475,12 +588,31 @@ static char * __init unpack_to_rootfs(ch
+ inptr = 0;
+ outcnt = 0; /* bytes in output buffer */
+ bytes_out = 0;
+- crc = (ulg)0xffffffffL; /* shift register contents */
+- makecrc();
+- gunzip();
+- if (state != Reset)
++ if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
++ {
++ printk( KERN_NOTICE "detected gzip initramfs\n");
++ crc = (ulg)0xffffffffL; /* shift register contents */
++ makecrc();
++ gunzip();
++ if (state != Reset)
+ error("junk in gzipped archive");
+- this_header = saved_offset + inptr;
++ }
++#ifdef CONFIG_LZMA_INITRAM_FS
++ else if( inbuf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0
++ && buf[11] == 0 && buf[12] == 0 )
++ {
++ printk( KERN_NOTICE "detected lzma initramfs\n");
++ lzma_unzip();
++ }
++#endif
++ else
++ {
++ // skip forward ?
++ crc = (ulg)0xffffffffL; /* shift register contents */
++ makecrc();
++ gunzip();
++ }
++ this_header = saved_offset + inptr;
+ buf += inptr;
+ len -= inptr;
+ }
+diff -rduNp linux-2.6.22.1.oorig/kernel/Makefile linux-2.6.22.1/kernel/Makefile
+--- linux-2.6.22.1.oorig/kernel/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/kernel/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -66,7 +66,7 @@ $(obj)/configs.o: $(obj)/config_data.h
+ # config_data.h contains the same information as ikconfig.h but gzipped.
+ # Info from config_data can be extracted from /proc/config*
+ targets += config_data.gz
+-$(obj)/config_data.gz: .config FORCE
++$(obj)/config_data.gz: .miniconfig FORCE
+ $(call if_changed,gzip)
+
+ quiet_cmd_ikconfiggz = IKCFG $@
+diff -rduNp linux-2.6.22.1.oorig/kernel/configs.c linux-2.6.22.1/kernel/configs.c
+--- linux-2.6.22.1.oorig/kernel/configs.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/kernel/configs.c 2007-07-24 14:17:46.000000000 +0200
+@@ -79,7 +79,7 @@ static int __init ikconfig_init(void)
+ struct proc_dir_entry *entry;
+
+ /* create the current config file */
+- entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
++ entry = create_proc_entry("miniconfig.gz", S_IFREG | S_IRUGO,
+ &proc_root);
+ if (!entry)
+ return -ENOMEM;
+@@ -95,7 +95,7 @@ static int __init ikconfig_init(void)
+
+ static void __exit ikconfig_cleanup(void)
+ {
+- remove_proc_entry("config.gz", &proc_root);
++ remove_proc_entry("miniconfig.gz", &proc_root);
+ }
+
+ module_init(ikconfig_init);
+diff -rduNp linux-2.6.22.1.oorig/kernel/time/clocksource.c linux-2.6.22.1/kernel/time/clocksource.c
+--- linux-2.6.22.1.oorig/kernel/time/clocksource.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/kernel/time/clocksource.c 2007-07-24 14:17:46.000000000 +0200
+@@ -87,8 +87,8 @@ static void clocksource_ratewd(struct cl
+ if (delta > -WATCHDOG_THRESHOLD && delta < WATCHDOG_THRESHOLD)
+ return;
+
+- printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
+- cs->name, delta);
++/* printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
++ cs->name, delta); */
+ cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
+ clocksource_change_rating(cs, 0);
+ cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
+diff -rduNp linux-2.6.22.1.oorig/miniconfig.sh linux-2.6.22.1/miniconfig.sh
+--- linux-2.6.22.1.oorig/miniconfig.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/miniconfig.sh 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,2 @@
++#!/bin/sh -f
++make allnoconfig KCONFIG_ALLCONFIG=.miniconfig
+diff -rduNp linux-2.6.22.1.oorig/scripts/Makefile.lib linux-2.6.22.1/scripts/Makefile.lib
+--- linux-2.6.22.1.oorig/scripts/Makefile.lib 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/scripts/Makefile.lib 2007-07-24 14:17:46.000000000 +0200
+@@ -162,4 +162,9 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS)
+ quiet_cmd_gzip = GZIP $@
+ cmd_gzip = gzip -f -9 < $< > $@
+
++# LZMA
++#
++quiet_cmd_lzma = LZMA $@
++cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++
+
+diff -rduNp linux-2.6.22.1.oorig/scripts/gen_lzma_initramfs_list.sh linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh
+--- linux-2.6.22.1.oorig/scripts/gen_lzma_initramfs_list.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,292 @@
++#!/bin/bash
++# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
++# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
++#
++# Released under the terms of the GNU GPL
++#
++# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
++# the cpio archive, and gzip to pack it.
++# The script may also be used to generate the inputfile used for gen_init_cpio
++# This script assumes that gen_init_cpio is located in usr/ directory
++
++# error out on errors
++set -e
++
++usage() {
++cat << EOF
++Usage:
++$0 [-o <file>] [-u <uid>] [-g <gid>] { -s | -d | <cpio_source>} ...
++ -o <file> Create lzma initramfs file named <file> using
++ gen_init_cpio and lzma
++ -u <uid> User ID to map to user ID 0 (root).
++ <uid> is only meaningful if <cpio_source>
++ is a directory.
++ -g <gid> Group ID to map to group ID 0 (root).
++ <gid> is only meaningful if <cpio_source>
++ is a directory.
++ <cpio_source> File list or directory for cpio archive.
++ If <cpio_source> is a .cpio file it will be used
++ as direct input to initramfs.
++ -s Create lzma file with small dictionary size
++ -d Output the default cpio list.
++
++All options except -o and -l may be repeated and are interpreted
++sequentially and immediately. -u and -g states are preserved across
++<cpio_source> options so an explicit "-u 0 -g 0" is required
++to reset the root/group mapping.
++EOF
++}
++
++list_default_initramfs() {
++ # echo usr/kinit/kinit
++ :
++}
++
++default_initramfs() {
++ cat <<-EOF >> ${output}
++ # This is a very simple, default initramfs
++
++ dir /dev 0755 0 0
++ nod /dev/console 0600 0 0 c 5 1
++ dir /root 0700 0 0
++ # file /kinit usr/kinit/kinit 0755 0 0
++ # slink /init kinit 0755 0 0
++ EOF
++}
++
++filetype() {
++ local argv1="$1"
++
++ # symlink test must come before file test
++ if [ -L "${argv1}" ]; then
++ echo "slink"
++ elif [ -f "${argv1}" ]; then
++ echo "file"
++ elif [ -d "${argv1}" ]; then
++ echo "dir"
++ elif [ -b "${argv1}" -o -c "${argv1}" ]; then
++ echo "nod"
++ elif [ -p "${argv1}" ]; then
++ echo "pipe"
++ elif [ -S "${argv1}" ]; then
++ echo "sock"
++ else
++ echo "invalid"
++ fi
++ return 0
++}
++
++list_print_mtime() {
++ :
++}
++
++print_mtime() {
++ local my_mtime="0"
++
++ if [ -e "$1" ]; then
++ my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
++ fi
++
++ echo "# Last modified: ${my_mtime}" >> ${output}
++ echo "" >> ${output}
++}
++
++list_parse() {
++ echo "$1 \\"
++}
++
++# for each file print a line in following format
++# <filetype> <name> <path to file> <octal mode> <uid> <gid>
++# for links, devices etc the format differs. See gen_init_cpio for details
++parse() {
++ local location="$1"
++ local name="${location/${srcdir}//}"
++ # change '//' into '/'
++ name="${name//\/\///}"
++ local mode="$2"
++ local uid="$3"
++ local gid="$4"
++ local ftype=$(filetype "${location}")
++ # remap uid/gid to 0 if necessary
++ [ "$uid" -eq "$root_uid" ] && uid=0
++ [ "$gid" -eq "$root_gid" ] && gid=0
++ local str="${mode} ${uid} ${gid}"
++
++ [ "${ftype}" == "invalid" ] && return 0
++ [ "${location}" == "${srcdir}" ] && return 0
++
++ case "${ftype}" in
++ "file")
++ str="${ftype} ${name} ${location} ${str}"
++ ;;
++ "nod")
++ local dev_type=
++ local maj=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{sub(/,/, "", $5); print $5}')
++ local min=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{print $6}')
++
++ if [ -b "${location}" ]; then
++ dev_type="b"
++ else
++ dev_type="c"
++ fi
++ str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
++ ;;
++ "slink")
++ local target=$(LC_ALL=C ls -l "${location}" | \
++ gawk '{print $11}')
++ str="${ftype} ${name} ${target} ${str}"
++ ;;
++ *)
++ str="${ftype} ${name} ${str}"
++ ;;
++ esac
++
++ echo "${str}" >> ${output}
++
++ return 0
++}
++
++unknown_option() {
++ printf "ERROR: unknown option \"$arg\"\n" >&2
++ printf "If the filename validly begins with '-', " >&2
++ printf "then it must be prefixed\n" >&2
++ printf "by './' so that it won't be interpreted as an option." >&2
++ printf "\n" >&2
++ usage >&2
++ exit 1
++}
++
++list_header() {
++ :
++}
++
++header() {
++ printf "\n#####################\n# $1\n" >> ${output}
++}
++
++# process one directory (incl sub-directories)
++dir_filelist() {
++ ${dep_list}header "$1"
++
++ srcdir=$(echo "$1" | sed -e 's://*:/:g')
++ dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
++
++ # If $dirlist is only one line, then the directory is empty
++ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
++ ${dep_list}print_mtime "$1"
++
++ echo "${dirlist}" | \
++ while read x; do
++ ${dep_list}parse ${x}
++ done
++ fi
++}
++
++# if only one file is specified and it is .cpio file then use it direct as fs
++# if a directory is specified then add all files in given direcotry to fs
++# if a regular file is specified assume it is in gen_initramfs format
++input_file() {
++ source="$1"
++ if [ -f "$1" ]; then
++ ${dep_list}header "$1"
++ is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
++ if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
++ cpio_file=$1
++ [ ! -z ${dep_list} ] && echo "$1"
++ return 0
++ fi
++ if [ -z ${dep_list} ]; then
++ print_mtime "$1" >> ${output}
++ cat "$1" >> ${output}
++ else
++ cat "$1" | while read type dir file perm ; do
++ if [ "$type" == "file" ]; then
++ echo "$file \\";
++ fi
++ done
++ fi
++ elif [ -d "$1" ]; then
++ dir_filelist "$1"
++ else
++ echo " ${prog}: Cannot open '$1'" >&2
++ exit 1
++ fi
++}
++
++prog=$0
++root_uid=0
++root_gid=0
++dep_list=
++cpio_file=
++cpio_list=
++output="/dev/stdout"
++output_file=""
++opt=""
++
++arg="$1"
++case "$arg" in
++ "-l") # files included in initramfs - used by kbuild
++ dep_list="list_"
++ echo "deps_initramfs := \\"
++ shift
++ ;;
++ "-o") # generate lzma-ed cpio image named $1
++ shift
++ output_file="$1"
++ cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
++ output=${cpio_list}
++ shift
++ ;;
++esac
++while [ $# -gt 0 ]; do
++ arg="$1"
++ shift
++ case "$arg" in
++ "-u") # map $1 to uid=0 (root)
++ root_uid="$1"
++ shift
++ ;;
++ "-g") # map $1 to gid=0 (root)
++ root_gid="$1"
++ shift
++ ;;
++ "-s")
++ opt="-d16"
++ ;;
++ "-d") # display default initramfs list
++ default_list="$arg"
++ ${dep_list}default_initramfs
++ ;;
++ "-h")
++ usage
++ exit 0
++ ;;
++ *)
++ case "$arg" in
++ "-"*)
++ unknown_option
++ ;;
++ *) # input file/dir - process it
++ input_file "$arg" "$#"
++ ;;
++ esac
++ ;;
++ esac
++done
++
++# If output_file is set we will generate cpio archive and lzma it
++# we are carefull to delete tmp files
++if [ ! -z ${output_file} ]; then
++ if [ -z ${cpio_file} ]; then
++ cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
++ usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
++ else
++ cpio_tfile=${cpio_file}
++ fi
++ rm ${cpio_list}
++ lzma e ${cpio_tfile} ${output_file} ${opt}
++ [ -z ${cpio_file} ] && rm ${cpio_tfile}
++fi
++exit 0
+diff -rduNp linux-2.6.22.1.oorig/shrinkconfig.sh linux-2.6.22.1/shrinkconfig.sh
+--- linux-2.6.22.1.oorig/shrinkconfig.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.1/shrinkconfig.sh 2007-07-24 14:17:46.000000000 +0200
+@@ -0,0 +1,79 @@
++#! /bin/bash
++
++# shrinkconfig copyright 2006 by Rob Landley <rob@landley.net>
++# Licensed under the GNU General Public License version 2.
++
++if [ $# -ne 1 ]
++then
++ echo "Turns current .config into a miniconfig file."
++ echo "Usage: shrinkconfig mini.config"
++ exit 1
++fi
++
++if [ ! -f .config ]
++then
++ echo "Need a .config file to shrink."
++ exit 1
++fi
++LENGTH=$(wc -l < .config)
++
++OUTPUT="$1"
++cp .config "$OUTPUT"
++if [ $? -ne 0 ]
++then
++ echo "Couldn't create $OUTPUT"
++ exit 1
++fi
++
++# If we get interrupted, clean up the mess
++
++KERNELOUTPUT=""
++
++function cleanup
++{
++ echo
++ echo "Interrupted."
++ [ ! -z "$KERNELOUTPUT" ] && rm -rf "$KERNELOUTPUT"
++ rm "$OUTPUT"
++ exit 1
++}
++
++trap cleanup HUP INT QUIT TERM
++
++# Since the "O=" argument to make doesn't work recursively, we need to jump
++# through a few hoops to avoid overwriting the .config that we're shrinking.
++
++# If we're building out of tree, we'll have absolute paths to source and build
++# directories in the Makefile.
++
++KERNELSRC=$(sed -n -e 's/KERNELSRC[^/]*:=[^/]*//p' Makefile)
++[ -z "$KERNELSRC" ] && KERNELSRC=$(pwd)
++KERNELOUTPUT=`pwd`/.config.minitemp
++
++mkdir -p "$KERNELOUTPUT" || exit 1
++
++echo "Shrinking .config to $OUTPUT..."
++
++for I in $(seq 1 $LENGTH)
++do
++ echo -n -e "\r"$I/$LENGTH lines $(wc -c < "$OUTPUT") bytes
++
++ sed -n "${I}!p" "$OUTPUT" > "$KERNELOUTPUT"/.config.test
++ # Do a config with this file
++ make -C "$KERNELSRC" O="$KERNELOUTPUT" allnoconfig KCONFIG_ALLCONFIG="$KERNELOUTPUT"/.config.test > /dev/null
++
++ # Compare. The date changes, so expect a small difference each time.
++ D=$(diff "$KERNELOUTPUT"/.config .config | wc -l)
++ if [ $D -eq 4 ]
++ then
++ mv "$KERNELOUTPUT"/.config.test "$OUTPUT"
++ LENGTH=$[$LENGTH-1]
++ else
++ I=$[$I + 1]
++ fi
++done
++
++rm -rf "$KERNELOUTPUT"
++
++# One extra echo to preserve status line.
++echo
+diff -rduNp linux-2.6.22.1.oorig/usr/Makefile linux-2.6.22.1/usr/Makefile
+--- linux-2.6.22.1.oorig/usr/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-2.6.22.1/usr/Makefile 2007-07-24 14:17:46.000000000 +0200
+@@ -19,6 +19,7 @@ $(obj)/initramfs_data.o: $(obj)/initramf
+
+ hostprogs-y := gen_init_cpio
+ initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
++lzma_initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
+ ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+ $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
+ ramfs-args := \
+@@ -36,6 +37,14 @@ endif
+ quiet_cmd_initfs = GEN $@
+ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
+
++ifdef CONFIG_LZMA_INITRAM_FS_SMALLMEM
++quiet_cmd_lzma_initfs = LZRAMFS $@
++ cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) -s $(ramfs-input)
++else
++quiet_cmd_lzma_initfs = LZRAMFS $@
++ cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) $(ramfs-input)
++endif
++
+ targets := initramfs_data.cpio.gz
+ # do not try to update files included in initramfs
+ $(deps_initramfs): ;
+@@ -48,5 +57,9 @@ $(deps_initramfs): klibcdirs
+ # 4) arguments to gen_initramfs.sh changes
+ $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+ $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
++ifdef CONFIG_LZMA_INITRAM_FS
++ $(call if_changed,lzma_initfs)
++else
+ $(call if_changed,initfs)
++endif
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-002-lzma-vmlinuz.01.patch b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-002-lzma-vmlinuz.01.patch
new file mode 100644
index 0000000000..05361ff9d4
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-002-lzma-vmlinuz.01.patch
@@ -0,0 +1,54 @@
+diff -rdup linux-2.6.21.5.oorig/arch/i386/boot/compressed/Makefile linux-2.6.21.5/arch/i386/boot/compressed/Makefile
+--- linux-2.6.21.5.oorig/arch/i386/boot/compressed/Makefile 2007-07-24 13:08:51.000000000 +0200
++++ linux-2.6.21.5/arch/i386/boot/compressed/Makefile 2007-07-24 14:54:38.000000000 +0200
+@@ -4,7 +4,7 @@
+ # create a compressed vmlinux image from the original vmlinux
+ #
+
+-tragets := head.o lzma_misc.o piggy.o \
++targets := head.o lzma_misc.o piggy.o \
+ vmlinux.bin.all vmlinux.relocs \
+ vmlinux vmlinux.bin vmlinux.bin.gz
+ EXTRA_AFLAGS := -traditional
+diff -rdup linux-2.6.21.5.oorig/scripts/gen_lzma_initramfs_list.sh linux-2.6.21.5/scripts/gen_lzma_initramfs_list.sh
+--- linux-2.6.21.5.oorig/scripts/gen_lzma_initramfs_list.sh 2007-07-24 13:08:51.000000000 +0200
++++ linux-2.6.21.5/scripts/gen_lzma_initramfs_list.sh 2007-07-24 15:12:10.000000000 +0200
+@@ -253,7 +253,7 @@ while [ $# -gt 0 ]; do
+ shift
+ ;;
+ "-s")
+- opt="-d16"
++ #opt="-d16" ? what was that supposed to do?
+ ;;
+ "-d") # display default initramfs list
+ default_list="$arg"
+@@ -286,7 +286,7 @@ if [ ! -z ${output_file} ]; then
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+- lzma e ${cpio_tfile} ${output_file} ${opt}
++ lzma -z ${cpio_tfile} ${opt} -c > ${output_file}
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+ fi
+ exit 0
+--- linux-2.6.21.5.oorig/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 15:24:44.000000000 +0200
++++ linux-2.6.21.5/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 17:09:40.000000000 +0200
+@@ -241,7 +241,6 @@ static int lzma_unzip(uch* output)
+
+ static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
+ {
+- static unsigned int i = 0;
+ static unsigned char val;
+ *bufferSize = 1;
+ val = get_byte();
+--- linux-2.6.21.5.oorig/scripts/Makefile.lib 2007-07-24 15:24:44.000000000 +0200
++++ linux-2.6.21.5/scripts/Makefile.lib 2007-07-24 18:03:57.000000000 +0200
+@@ -165,6 +165,7 @@ cmd_gzip = gzip -f -9 < $< > $@
+ # LZMA
+ #
+ quiet_cmd_lzma = LZMA $@
+-cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++#cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
++cmd_lzma = lzma -z $< -c > $@
+
+
diff --git a/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-003-lzma-vmlinuz.patch b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-003-lzma-vmlinuz.patch
new file mode 100644
index 0000000000..8fb7e882d1
--- /dev/null
+++ b/cleopatre/buildroot/toolchain/kernel-headers/lzma/linux-2.6.22.1-003-lzma-vmlinuz.patch
@@ -0,0 +1,44 @@
+diff -rdup linux-2.6.22.1.old/scripts/Makefile.lib linux-2.6.22.1/scripts/Makefile.lib
+--- linux-2.6.22.1.old/scripts/Makefile.lib 2007-08-21 16:32:19.000000000 +0200
++++ linux-2.6.22.1/scripts/Makefile.lib 2007-08-21 16:43:20.000000000 +0200
+@@ -166,6 +166,6 @@ cmd_gzip = gzip -f -9 < $< > $@
+ #
+ quiet_cmd_lzma = LZMA $@
+ #cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
+-cmd_lzma = lzma -z $< -c > $@
++cmd_lzma = $(LZMA) -z $< -c > $@
+
+
+diff -rdup linux-2.6.22.1.old/scripts/gen_lzma_initramfs_list.sh linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh
+--- linux-2.6.22.1.old/scripts/gen_lzma_initramfs_list.sh 2007-08-21 16:32:19.000000000 +0200
++++ linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh 2007-08-21 16:42:56.000000000 +0200
+@@ -11,7 +11,7 @@
+
+ # error out on errors
+ set -e
+-
++test "x$LZMA" = "x" && LZMA=lzma
+ usage() {
+ cat << EOF
+ Usage:
+@@ -286,7 +286,7 @@ if [ ! -z ${output_file} ]; then
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+- lzma -z ${cpio_tfile} ${opt} -c > ${output_file}
++ $LZMA -z ${cpio_tfile} ${opt} -c > ${output_file}
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+ fi
+ exit 0
+diff -rdup linux-2.6.22.1.old/usr/Makefile linux-2.6.22.1/usr/Makefile
+--- linux-2.6.22.1.old/usr/Makefile 2007-08-21 16:32:19.000000000 +0200
++++ linux-2.6.22.1/usr/Makefile 2007-08-21 16:46:22.000000000 +0200
+@@ -19,7 +19,7 @@ $(obj)/initramfs_data.o: $(obj)/initramf
+
+ hostprogs-y := gen_init_cpio
+ initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
+-lzma_initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
++lzma_initramfs := LZMA=$(LZMA) $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
+ ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+ $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
+ ramfs-args := \